Coverage for manila/tests/share/test_api.py: 99%

3236 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright 2012 NetApp. All rights reserved. 

2# Copyright (c) 2015 Tom Barron. All rights reserved. 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); you may 

5# not use this file except in compliance with the License. You may obtain 

6# a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

13# License for the specific language governing permissions and limitations 

14# under the License. 

15"""Unit tests for the Share API module.""" 

16 

17import copy 

18import datetime 

19import json 

20from unittest import mock 

21 

22 

23import ddt 

24from oslo_config import cfg 

25from oslo_utils import timeutils 

26from oslo_utils import uuidutils 

27from webob import exc as webob_exc 

28 

29from manila.common import constants 

30from manila import context 

31from manila.data import rpcapi as data_rpc 

32from manila import db as db_api 

33from manila.db.sqlalchemy import models 

34from manila import exception 

35from manila.keymgr import barbican as barbican_api 

36from manila import policy 

37from manila import quota 

38from manila import share 

39from manila.share import api as share_api 

40from manila.share import share_types 

41from manila import test 

42from manila.tests import db_utils 

43from manila.tests import fake_share as fakes 

44from manila.tests import utils as test_utils 

45from manila import utils 

46 

47CONF = cfg.CONF 

48 

49 

50_FAKE_LIST_OF_ALL_SHARES = [ 

51 { 

52 'name': 'foo', 

53 'description': 'ds', 

54 'status': constants.STATUS_AVAILABLE, 

55 'project_id': 'fake_pid_1', 

56 'share_server_id': 'fake_server_1', 

57 }, 

58 { 

59 'name': 'bar', 

60 'status': constants.STATUS_ERROR, 

61 'project_id': 'fake_pid_2', 

62 'share_server_id': 'fake_server_2', 

63 }, 

64 { 

65 'name': 'foo1', 

66 'description': 'ds1', 

67 'status': constants.STATUS_AVAILABLE, 

68 'project_id': 'fake_pid_2', 

69 'share_server_id': 'fake_server_3', 

70 }, 

71 { 

72 'name': 'bar', 

73 'status': constants.STATUS_ERROR, 

74 'project_id': 'fake_pid_2', 

75 'share_server_id': 'fake_server_3', 

76 }, 

77] 

78 

79 

80_FAKE_LIST_OF_ALL_SNAPSHOTS = [ 

81 { 

82 'name': 'foo', 

83 'status': constants.STATUS_AVAILABLE, 

84 'project_id': 'fake_pid_1', 

85 'share_id': 'fake_server_1', 

86 }, 

87 { 

88 'name': 'bar', 

89 'status': constants.STATUS_ERROR, 

90 'project_id': 'fake_pid_2', 

91 'share_id': 'fake_server_2', 

92 }, 

93 { 

94 'name': 'foo', 

95 'status': constants.STATUS_AVAILABLE, 

96 'project_id': 'fake_pid_2', 

97 'share_id': 'fake_share_id_3', 

98 }, 

99 { 

100 'name': 'bar', 

101 'status': constants.STATUS_ERROR, 

102 'project_id': 'fake_pid_2', 

103 'share_id': 'fake_share_id_3', 

104 }, 

105] 

106 

107 

108@ddt.ddt 

109class ShareAPITestCase(test.TestCase): 

110 

111 def setUp(self): 

112 super(ShareAPITestCase, self).setUp() 

113 self.context = context.get_admin_context() 

114 self.scheduler_rpcapi = mock.Mock() 

115 self.share_rpcapi = mock.Mock() 

116 self.api = share.API() 

117 self.mock_object(self.api.db, 'resource_lock_get_all', 

118 mock.Mock(return_value=([], None))) 

119 self.mock_object(self.api, 'scheduler_rpcapi', self.scheduler_rpcapi) 

120 self.mock_object(self.api, 'share_rpcapi', self.share_rpcapi) 

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

122 lambda *args, **kwargs: None) 

123 

124 self.dt_utc = timeutils.utcnow() 

125 self.mock_object(timeutils, 'utcnow', 

126 mock.Mock(return_value=self.dt_utc)) 

127 self.mock_object(share_api.policy, 'check_policy') 

128 self._setup_sized_share_types() 

129 

130 def _setup_sized_share_types(self): 

131 """create a share type with size limit""" 

132 spec_dict = {share_types.MIN_SIZE_KEY: 2, 

133 share_types.MAX_SIZE_KEY: 4, 

134 share_types.MAX_EXTEND_SIZE_KEY: 6} 

135 db_utils.create_share_type(name='limit', extra_specs=spec_dict) 

136 self.sized_sha_type = db_api.share_type_get_by_name(self.context, 

137 'limit') 

138 

139 def _setup_create_mocks(self, protocol='nfs', **kwargs): 

140 share = db_utils.create_share( 

141 user_id=self.context.user_id, 

142 project_id=self.context.project_id, 

143 share_type_id=kwargs.pop('share_type_id', 'fake'), 

144 **kwargs 

145 ) 

146 share_data = { 

147 'share_proto': protocol, 

148 'size': 1, 

149 'display_name': 'fakename', 

150 'display_description': 'fakedesc', 

151 'availability_zone': 'fakeaz' 

152 } 

153 

154 self.mock_object(db_api, 'share_create', mock.Mock(return_value=share)) 

155 self.mock_object(self.api, 'create_instance') 

156 

157 return share, share_data 

158 

159 def _setup_create_instance_mocks(self): 

160 host = 'fake' 

161 share_type_id = "fake_share_type" 

162 share = db_utils.create_share( 

163 user_id=self.context.user_id, 

164 project_id=self.context.project_id, 

165 create_share_instance=False, 

166 ) 

167 share_instance = db_utils.create_share_instance( 

168 share_id=share['id'], 

169 share_type_id=share_type_id) 

170 share_type = { 

171 'fake': 'fake', 

172 'mount_point_name_support': False 

173 } 

174 self.mock_object(db_api, 'share_instance_create', 

175 mock.Mock(return_value=share_instance)) 

176 self.mock_object(db_api, 'share_type_get', 

177 mock.Mock(return_value=share_type)) 

178 az_mock = mock.Mock() 

179 type(az_mock.return_value).id = mock.PropertyMock( 

180 return_value='fake_id') 

181 self.mock_object(db_api, 'availability_zone_get', az_mock) 

182 self.mock_object(self.api.share_rpcapi, 'create_share_instance') 

183 self.mock_object(self.api.scheduler_rpcapi, 'create_share_instance') 

184 

185 return host, share, share_instance 

186 

187 def _setup_create_from_snapshot_mocks(self, use_scheduler=True, host=None): 

188 CONF.set_default("use_scheduler_creating_share_from_snapshot", 

189 use_scheduler) 

190 

191 share_type = fakes.fake_share_type() 

192 

193 original_share = db_utils.create_share( 

194 user_id=self.context.user_id, 

195 project_id=self.context.project_id, 

196 status=constants.STATUS_AVAILABLE, 

197 host=host if host else 'fake', 

198 size=1, 

199 share_type_id=share_type['id'], 

200 ) 

201 snapshot = db_utils.create_snapshot( 

202 share_id=original_share['id'], 

203 status=constants.STATUS_AVAILABLE, 

204 size=1 

205 ) 

206 

207 share, share_data = self._setup_create_mocks( 

208 snapshot_id=snapshot['id'], share_type_id=share_type['id']) 

209 request_spec = { 

210 'share_properties': share.to_dict(), 

211 'share_proto': share['share_proto'], 

212 'share_id': share['id'], 

213 'share_type': None, 

214 'snapshot_id': share['snapshot_id'], 

215 } 

216 

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

218 mock.Mock(return_value='reservation')) 

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

220 self.mock_object( 

221 share_types, 'get_share_type', mock.Mock(return_value=share_type)) 

222 

223 return snapshot, share, share_data, request_spec 

224 

225 def _setup_delete_mocks(self, status, snapshots=None, **kwargs): 

226 if snapshots is None: 

227 snapshots = [] 

228 share = db_utils.create_share(status=status, **kwargs) 

229 self.mock_object(db_api, 'share_delete') 

230 self.mock_object(db_api, 'share_server_update') 

231 self.mock_object(db_api, 'share_snapshot_get_all_for_share', 

232 mock.Mock(return_value=snapshots)) 

233 self.mock_object(db_api, 'share_backups_get_all', 

234 mock.Mock(return_value=[])) 

235 self.mock_object(self.api, 'delete_instance') 

236 return share 

237 

238 def _setup_delete_share_instance_mocks(self, **kwargs): 

239 share = db_utils.create_share(**kwargs) 

240 

241 self.mock_object(db_api, 'share_instance_update', 

242 mock.Mock(return_value=share.instance)) 

243 self.mock_object(self.api.share_rpcapi, 'delete_share_instance') 

244 self.mock_object(db_api, 'share_server_update') 

245 self.mock_object(db_api, 'share_instance_delete') 

246 

247 return share.instance 

248 

249 def test_get_all_admin_default_filters(self): 

250 self.mock_object(db_api, 'share_get_all_by_project', 

251 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0])) 

252 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

253 

254 shares = self.api.get_all(ctx) 

255 

256 db_api.share_get_all_by_project.assert_called_once_with( 

257 ctx, sort_dir='desc', sort_key='created_at', 

258 project_id='fake_pid_1', 

259 filters={'list_deferred_delete': True}, 

260 is_public=False 

261 ) 

262 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares) 

263 

264 def test_get_all_admin_filter_by_all_tenants(self): 

265 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

266 self.mock_object(db_api, 'share_get_all', 

267 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES)) 

268 self.mock_object(share_api.policy, 'check_policy', 

269 mock.Mock(return_value=True)) 

270 

271 shares = self.api.get_all(ctx, {'all_tenants': 1}) 

272 

273 db_api.share_get_all.assert_called_once_with( 

274 ctx, sort_dir='desc', sort_key='created_at', 

275 filters={'list_deferred_delete': True}) 

276 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES, shares) 

277 

278 def test_get_all_admin_filter_by_all_tenants_with_blank(self): 

279 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

280 self.mock_object(db_api, 'share_get_all', 

281 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES)) 

282 self.mock_object(share_api.policy, 'check_policy', 

283 mock.Mock(return_value=True)) 

284 

285 shares = self.api.get_all(ctx, {'all_tenants': ''}) 

286 

287 db_api.share_get_all.assert_called_once_with( 

288 ctx, sort_dir='desc', sort_key='created_at', 

289 filters={'list_deferred_delete': True}) 

290 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES, shares) 

291 

292 def test_get_all_admin_filter_by_all_tenants_with_false(self): 

293 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

294 self.mock_object(db_api, 'share_get_all_by_project', 

295 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0])) 

296 

297 shares = self.api.get_all(ctx, {'all_tenants': 'false'}) 

298 

299 db_api.share_get_all_by_project.assert_called_once_with( 

300 ctx, sort_dir='desc', sort_key='created_at', 

301 project_id='fake_pid_1', filters={'list_deferred_delete': True}, 

302 is_public=False 

303 ) 

304 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares) 

305 

306 def test_get_all_admin_filter_by_all_tenants_with_invaild_value(self): 

307 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

308 self.mock_object(db_api, 'share_get_all') 

309 self.assertRaises( 

310 exception.InvalidInput, 

311 self.api.get_all, ctx, {'all_tenants': 'wonk'}) 

312 

313 @ddt.data( 

314 ({'share_server_id': 'fake_share_server'}, 'list_by_share_server_id'), 

315 ({'host': 'fake_host'}, 'list_by_host'), 

316 ) 

317 @ddt.unpack 

318 def test_get_all_by_non_admin_using_admin_filter(self, filters, policy): 

319 

320 def fake_policy_checker(*args, **kwargs): 

321 if policy == args[2] and not args[0].is_admin: 

322 raise exception.NotAuthorized 

323 

324 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

325 mock_policy = self.mock_object( 

326 share_api.policy, 'check_policy', 

327 mock.Mock(side_effect=fake_policy_checker)) 

328 

329 self.assertRaises( 

330 exception.NotAuthorized, 

331 self.api.get_all, ctx, filters) 

332 

333 mock_policy.assert_has_calls([ 

334 mock.call( 

335 ctx, 'share', 

336 'list_shares_in_deferred_deletion_states', 

337 do_raise=False), 

338 mock.call(ctx, 'share', policy)]) 

339 

340 def test_get_all_admin_filter_by_share_server_and_all_tenants(self): 

341 # NOTE(vponomaryov): if share_server_id provided, 'all_tenants' opt 

342 # should not make any influence. 

343 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

344 self.mock_object(db_api, 'share_get_all_by_share_server', 

345 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[2:])) 

346 self.mock_object(db_api, 'share_get_all') 

347 self.mock_object(db_api, 'share_get_all_by_project') 

348 mock_policy = self.mock_object(share_api.policy, 'check_policy') 

349 shares = self.api.get_all( 

350 ctx, {'share_server_id': 'fake_server_3', 'all_tenants': 1}) 

351 mock_policy.assert_has_calls([ 

352 mock.call( 

353 ctx, 'share', 

354 'list_shares_in_deferred_deletion_states', 

355 do_raise=False), 

356 mock.call(ctx, 'share', 'list_all_projects', do_raise=False), 

357 mock.call(ctx, 'share', 'list_by_share_server_id')]) 

358 

359 db_api.share_get_all_by_share_server.assert_called_once_with( 

360 ctx, 'fake_server_3', sort_dir='desc', sort_key='created_at', 

361 filters={'list_deferred_delete': True}, 

362 ) 

363 db_api.share_get_all_by_project.assert_has_calls([]) 

364 db_api.share_get_all.assert_has_calls([]) 

365 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[2:], shares) 

366 

367 def test_get_all_admin_filter_by_name(self): 

368 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True) 

369 self.mock_object( 

370 db_api, 'share_get_all_by_project', 

371 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1::2])) 

372 expected_filters = {'display_name': 'bar', 

373 'list_deferred_delete': True} 

374 

375 shares = self.api.get_all(ctx, {'display_name': 'bar'}) 

376 

377 db_api.share_get_all_by_project.assert_called_once_with( 

378 ctx, sort_dir='desc', sort_key='created_at', 

379 project_id='fake_pid_2', filters=expected_filters, is_public=False 

380 ) 

381 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1::2], shares) 

382 

383 @ddt.data(({'display_name': 'fo'}, 0), ({'display_description': 'd'}, 0), 

384 ({'display_name': 'foo', 'display_description': 'd'}, 0), 

385 ({'display_name': 'foo'}, 1), ({'display_description': 'ds'}, 1), 

386 ({'display_name~': 'foo', 'display_description~': 'ds'}, 2), 

387 ({'display_name': 'foo', 'display_description~': 'ds'}, 1), 

388 ({'display_name~': 'foo', 'display_description': 'ds'}, 1)) 

389 @ddt.unpack 

390 def test_get_all_admin_filter_by_name_and_description( 

391 self, search_opts, get_share_number): 

392 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True) 

393 

394 expected_result = [] 

395 

396 if get_share_number == 2: 

397 expected_result = _FAKE_LIST_OF_ALL_SHARES[0::2] 

398 elif get_share_number == 1: 

399 expected_result = _FAKE_LIST_OF_ALL_SHARES[:1] 

400 

401 self.mock_object(db_api, 'share_get_all_by_project', 

402 mock.Mock(return_value=expected_result)) 

403 expected_filters = copy.copy(search_opts) 

404 expected_filters.update({'list_deferred_delete': True}) 

405 

406 shares = self.api.get_all(ctx, search_opts) 

407 

408 db_api.share_get_all_by_project.assert_called_once_with( 

409 ctx, sort_dir='desc', sort_key='created_at', 

410 project_id='fake_pid_2', 

411 filters=expected_filters, is_public=False 

412 ) 

413 self.assertEqual(get_share_number, len(shares)) 

414 self.assertEqual(expected_result, shares) 

415 

416 @ddt.data('id', 'path') 

417 def test_get_all_admin_filter_by_export_location(self, type): 

418 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True) 

419 self.mock_object(db_api, 'share_get_all_by_project', 

420 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1:])) 

421 

422 shares = self.api.get_all(ctx, {'export_location_' + type: 'test'}) 

423 

424 db_api.share_get_all_by_project.assert_called_once_with( 

425 ctx, sort_dir='desc', sort_key='created_at', 

426 project_id='fake_pid_2', 

427 filters={'export_location_' + type: 'test', 

428 'list_deferred_delete': True}, 

429 is_public=False 

430 ) 

431 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares) 

432 

433 def test_get_all_admin_filter_by_name_and_all_tenants(self): 

434 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True) 

435 self.mock_object(db_api, 'share_get_all', 

436 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[:1])) 

437 

438 shares = self.api.get_all(ctx, {'name': 'foo', 'all_tenants': 1}) 

439 

440 db_api.share_get_all.assert_called_once_with( 

441 ctx, sort_dir='desc', sort_key='created_at', 

442 filters={'list_deferred_delete': True}) 

443 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[:1], shares) 

444 

445 def test_get_all_admin_filter_by_status(self): 

446 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True) 

447 expected_filter = {'status': constants.STATUS_AVAILABLE, 

448 'list_deferred_delete': True} 

449 self.mock_object( 

450 db_api, 'share_get_all_by_project', 

451 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0::2])) 

452 

453 shares = self.api.get_all(ctx, {'status': constants.STATUS_AVAILABLE}) 

454 

455 db_api.share_get_all_by_project.assert_called_once_with( 

456 ctx, sort_dir='desc', sort_key='created_at', 

457 project_id='fake_pid_2', filters=expected_filter, is_public=False 

458 ) 

459 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0::2], shares) 

460 

461 def test_get_all_admin_filter_by_status_and_all_tenants(self): 

462 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True) 

463 self.mock_object( 

464 db_api, 'share_get_all', 

465 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1::2])) 

466 expected_filter = {'status': constants.STATUS_ERROR, 

467 'list_deferred_delete': True} 

468 shares = self.api.get_all( 

469 ctx, {'status': constants.STATUS_ERROR, 'all_tenants': 1}) 

470 db_api.share_get_all.assert_called_once_with( 

471 ctx, sort_dir='desc', sort_key='created_at', 

472 filters=expected_filter) 

473 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1::2], shares) 

474 

475 def test_get_all_non_admin_filter_by_all_tenants(self): 

476 # Expected share list only by project of non-admin user 

477 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=False) 

478 self.mock_object(db_api, 'share_get_all_by_project', 

479 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1:])) 

480 self.mock_policy_check = self.mock_object( 

481 policy, 'check_policy', mock.Mock(return_value=False)) 

482 

483 shares = self.api.get_all(ctx, {'all_tenants': 1}) 

484 

485 db_api.share_get_all_by_project.assert_called_once_with( 

486 ctx, sort_dir='desc', sort_key='created_at', 

487 project_id='fake_pid_2', filters={}, is_public=False 

488 ) 

489 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares) 

490 

491 def test_get_all_non_admin_with_name_and_status_filters(self): 

492 ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=False) 

493 self.mock_object( 

494 db_api, 'share_get_all_by_project', 

495 mock.Mock(side_effect=[ 

496 _FAKE_LIST_OF_ALL_SHARES[1::2], 

497 _FAKE_LIST_OF_ALL_SHARES[2::4]])) 

498 self.mock_policy_check = self.mock_object( 

499 policy, 'check_policy', mock.Mock(return_value=False)) 

500 

501 shares = self.api.get_all( 

502 ctx, {'name': 'bar', 'status': constants.STATUS_ERROR}) 

503 

504 expected_filter_1 = {'status': constants.STATUS_ERROR} 

505 expected_filter_2 = {'status': constants.STATUS_AVAILABLE} 

506 

507 db_api.share_get_all_by_project.assert_called_once_with( 

508 ctx, sort_dir='desc', sort_key='created_at', 

509 project_id='fake_pid_2', filters=expected_filter_1, is_public=False 

510 ) 

511 

512 # two items expected, one filtered 

513 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1::2], shares) 

514 

515 # one item expected, two filtered 

516 shares = self.api.get_all( 

517 ctx, {'name': 'foo1', 'status': constants.STATUS_AVAILABLE}) 

518 

519 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[2::4], shares) 

520 db_api.share_get_all_by_project.assert_has_calls([ 

521 mock.call( 

522 ctx, sort_dir='desc', sort_key='created_at', 

523 project_id='fake_pid_2', filters=expected_filter_1, 

524 is_public=False), 

525 mock.call( 

526 ctx, sort_dir='desc', sort_key='created_at', 

527 project_id='fake_pid_2', filters=expected_filter_2, 

528 is_public=False), 

529 ]) 

530 

531 @ddt.data('True', 'true', '1', 'yes', 'y', 'on', 't', True) 

532 def test_get_all_non_admin_public(self, is_public): 

533 ctx = context.RequestContext('fake_uid', 'fake_pid_2', 

534 is_admin=False) 

535 self.mock_object(db_api, 'share_get_all_by_project', mock.Mock( 

536 return_value=_FAKE_LIST_OF_ALL_SHARES[1:])) 

537 self.mock_policy_check = self.mock_object( 

538 policy, 'check_policy', mock.Mock(return_value=False)) 

539 shares = self.api.get_all(ctx, {'is_public': is_public}) 

540 db_api.share_get_all_by_project.assert_called_once_with( 

541 ctx, sort_dir='desc', sort_key='created_at', 

542 project_id='fake_pid_2', filters={}, is_public=True 

543 ) 

544 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares) 

545 

546 @ddt.data('False', 'false', '0', 'no', 'n', 'off', 'f', False) 

547 def test_get_all_non_admin_not_public(self, is_public): 

548 ctx = context.RequestContext('fake_uid', 'fake_pid_2', 

549 is_admin=False) 

550 self.mock_object(db_api, 'share_get_all_by_project', mock.Mock( 

551 return_value=_FAKE_LIST_OF_ALL_SHARES[1:])) 

552 self.mock_policy_check = self.mock_object( 

553 policy, 'check_policy', mock.Mock(return_value=False)) 

554 

555 shares = self.api.get_all(ctx, {'is_public': is_public}) 

556 db_api.share_get_all_by_project.assert_called_once_with( 

557 ctx, sort_dir='desc', sort_key='created_at', 

558 project_id='fake_pid_2', filters={}, is_public=False 

559 ) 

560 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares) 

561 

562 @ddt.data('truefoo', 'bartrue') 

563 def test_get_all_invalid_public_value(self, is_public): 

564 ctx = context.RequestContext('fake_uid', 'fake_pid_2', 

565 is_admin=False) 

566 self.assertRaises(ValueError, self.api.get_all, 

567 ctx, {'is_public': is_public}) 

568 

569 def test_get_all_with_sorting_valid(self): 

570 self.mock_object(db_api, 'share_get_all_by_project', 

571 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0])) 

572 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

573 self.mock_policy_check = self.mock_object( 

574 policy, 'check_policy', mock.Mock(return_value=False)) 

575 

576 shares = self.api.get_all(ctx, sort_key='status', sort_dir='asc') 

577 

578 db_api.share_get_all_by_project.assert_called_once_with( 

579 ctx, sort_dir='asc', sort_key='status', 

580 project_id='fake_pid_1', filters={}, is_public=False 

581 ) 

582 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares) 

583 

584 def test_get_all_sort_key_invalid(self): 

585 self.mock_object(db_api, 'share_get_all_by_project', 

586 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0])) 

587 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

588 self.assertRaises( 

589 exception.InvalidInput, 

590 self.api.get_all, 

591 ctx, 

592 sort_key=1, 

593 ) 

594 

595 def test_get_all_sort_dir_invalid(self): 

596 self.mock_object(db_api, 'share_get_all_by_project', 

597 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0])) 

598 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

599 self.assertRaises( 

600 exception.InvalidInput, 

601 self.api.get_all, 

602 ctx, 

603 sort_dir=1, 

604 ) 

605 

606 def _get_all_filter_metadata_or_extra_specs_valid(self, key): 

607 self.mock_object(db_api, 'share_get_all_by_project', 

608 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0])) 

609 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

610 mock_policy_check = self.mock_object( 

611 policy, 'check_policy', mock.Mock(return_value=False)) 

612 

613 search_opts = {key: {'foo1': 'bar1', 'foo2': 'bar2'}} 

614 

615 shares = self.api.get_all(ctx, search_opts=search_opts.copy()) 

616 

617 if key == 'extra_specs': 

618 mock_policy_check.assert_has_calls([ 

619 mock.call(ctx, 'share_types_extra_spec', 'index'), 

620 mock.call( 

621 ctx, 'share', 

622 'list_shares_in_deferred_deletion_states', 

623 do_raise=False)]) 

624 else: 

625 mock_policy_check.assert_called_once_with( 

626 ctx, 'share', 

627 'list_shares_in_deferred_deletion_states', 

628 do_raise=False), 

629 

630 db_api.share_get_all_by_project.assert_called_once_with( 

631 ctx, sort_dir='desc', sort_key='created_at', 

632 project_id='fake_pid_1', filters=search_opts, is_public=False) 

633 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares) 

634 

635 def test_get_all_filter_by_metadata(self): 

636 self._get_all_filter_metadata_or_extra_specs_valid(key='metadata') 

637 

638 def test_get_all_filter_by_extra_specs(self): 

639 self._get_all_filter_metadata_or_extra_specs_valid(key='extra_specs') 

640 

641 def _get_all_filter_metadata_or_extra_specs_invalid(self, key): 

642 self.mock_object(db_api, 'share_get_all_by_project', 

643 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0])) 

644 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

645 search_opts = {key: "{'foo': 'bar'}"} 

646 self.assertRaises(exception.InvalidInput, self.api.get_all, ctx, 

647 search_opts=search_opts) 

648 if key == 'extra_specs': 

649 share_api.policy.check_policy.assert_called_once_with( 

650 ctx, 'share_types_extra_spec', 'index') 

651 

652 def test_get_all_filter_by_invalid_metadata(self): 

653 self._get_all_filter_metadata_or_extra_specs_invalid(key='metadata') 

654 

655 def test_get_all_filter_by_invalid_extra_specs(self): 

656 self._get_all_filter_metadata_or_extra_specs_invalid(key='extra_specs') 

657 

658 @ddt.data(True, False) 

659 def test_update_metadata_from_share_type_extra_specs(self, with_metadata): 

660 share_type = fakes.fake_share_type( 

661 extra_specs={ 

662 'driver_handles_share_servers': 'False', 

663 'fake_driver:dedupe': 'True', 

664 'fake_driver:encrypt': 'True', 

665 'fake_driver:snapshot_policy': 'daily', 

666 'provisioning:max_share_size': '10', 

667 } 

668 ) 

669 

670 user_metadata = {} 

671 if with_metadata: 

672 user_metadata = { 

673 'snapshot_policy': 'monthly', 

674 'tag': 't1', 

675 'max_share_size': '5', 

676 } 

677 

678 CONF.set_default( 

679 "driver_updatable_metadata", 

680 ['dedupe', 'snapshot_policy', 'thin_provisioning'], 

681 ) 

682 

683 result = self.api.update_metadata_from_share_type_extra_specs( 

684 self.context, 

685 share_type, 

686 user_metadata 

687 ) 

688 

689 if with_metadata: 

690 self.assertEqual( 

691 result, 

692 {'dedupe': 'True', 'snapshot_policy': 'monthly', 'tag': 't1', 

693 'max_share_size': '5'}) 

694 else: 

695 self.assertEqual( 

696 result, 

697 {'dedupe': 'True', 'snapshot_policy': 'daily'}) 

698 

699 def test_update_share_network_subnet_from_metadata(self): 

700 CONF.set_default( 

701 "driver_updatable_subnet_metadata", 

702 ['dedupe', 'snapshot_policy', 'thin_provisioning'], 

703 ) 

704 metadata = { 

705 'test_key': 'True', 

706 'snapshot_policy': 'monthly', 

707 } 

708 backend_metadata = { 

709 k: v for k, v in 

710 metadata.items() if k in CONF.driver_updatable_subnet_metadata} 

711 

712 self.mock_object( 

713 db_api, 'share_server_get_all_by_host_and_or_share_subnet', 

714 mock.Mock(return_value=['fake_share_server'])) 

715 mock_call = self.mock_object( 

716 self.api.share_rpcapi, 

717 'update_share_network_subnet_from_metadata') 

718 

719 self.api.update_share_network_subnet_from_metadata( 

720 self.context, 'fake_sn_id', 'fake_sn_subnet_id', metadata) 

721 mock_call.assert_called_once_with( 

722 self.context, 'fake_sn_id', 'fake_sn_subnet_id', 

723 'fake_share_server', backend_metadata) 

724 

725 def test_update_share_from_metadata(self): 

726 CONF.set_default( 

727 "driver_updatable_metadata", 

728 ['dedupe', 'snapshot_policy', 'thin_provisioning'], 

729 ) 

730 metadata = { 

731 'dedupe': 'True', 

732 'snapshot_policy': 'monthly', 

733 'max_share_size': '10' 

734 } 

735 backend_metadata = { 

736 k: v for k, v in metadata.items() if k != 'max_share_size'} 

737 

738 self.mock_object(self.api, 'get', mock.Mock(return_value='fake_share')) 

739 mock_call = self.mock_object( 

740 self.api.share_rpcapi, 

741 'update_share_from_metadata' 

742 ) 

743 

744 self.api.update_share_from_metadata(self.context, 'fake_id', metadata) 

745 mock_call.assert_called_once_with( 

746 self.context, 'fake_share', backend_metadata) 

747 

748 @ddt.data(True, False) 

749 def test_create_public_and_private_share(self, is_public): 

750 share, share_data = self._setup_create_mocks(is_public=is_public) 

751 az = share_data.pop('availability_zone') 

752 

753 self.api.create( 

754 self.context, 

755 share_data['share_proto'], 

756 share_data['size'], 

757 share_data['display_name'], 

758 share_data['display_description'], 

759 availability_zone=az 

760 ) 

761 

762 share['status'] = constants.STATUS_CREATING 

763 share['host'] = None 

764 

765 self.assertSubDictMatch(share_data, 

766 db_api.share_create.call_args[0][1]) 

767 

768 @ddt.data( 

769 {}, 

770 { 

771 constants.ExtraSpecs.SNAPSHOT_SUPPORT: True, 

772 }, 

773 { 

774 constants.ExtraSpecs.SNAPSHOT_SUPPORT: False, 

775 constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: False, 

776 }, 

777 { 

778 constants.ExtraSpecs.SNAPSHOT_SUPPORT: True, 

779 constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: False, 

780 }, 

781 { 

782 constants.ExtraSpecs.SNAPSHOT_SUPPORT: True, 

783 constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: True, 

784 } 

785 ) 

786 def test_create_default_snapshot_semantics(self, extra_specs): 

787 share, share_data = self._setup_create_mocks(is_public=False) 

788 az = share_data.pop('availability_zone') 

789 share_type = fakes.fake_share_type(extra_specs=extra_specs) 

790 

791 self.api.create( 

792 self.context, 

793 share_data['share_proto'], 

794 share_data['size'], 

795 share_data['display_name'], 

796 share_data['display_description'], 

797 availability_zone=az, 

798 share_type=share_type 

799 ) 

800 

801 share['status'] = constants.STATUS_CREATING 

802 share['host'] = None 

803 

804 share_data.update(extra_specs) 

805 if extra_specs.get('snapshot_support') is None: 

806 share_data['snapshot_support'] = False 

807 if extra_specs.get('create_share_from_snapshot_support') is None: 

808 share_data['create_share_from_snapshot_support'] = False 

809 

810 self.assertSubDictMatch(share_data, 

811 db_api.share_create.call_args[0][1]) 

812 

813 @ddt.data(*constants.SUPPORTED_SHARE_PROTOCOLS) 

814 def test_create_share_valid_protocol(self, proto): 

815 share, share_data = self._setup_create_mocks(protocol=proto) 

816 az = share_data.pop('availability_zone') 

817 

818 all_protos = ','.join( 

819 proto for proto in constants.SUPPORTED_SHARE_PROTOCOLS) 

820 data = dict(DEFAULT=dict(enabled_share_protocols=all_protos)) 

821 with test_utils.create_temp_config_with_opts(data): 

822 self.api.create( 

823 self.context, proto, share_data['size'], 

824 share_data['display_name'], 

825 share_data['display_description'], 

826 availability_zone=az) 

827 

828 share['status'] = constants.STATUS_CREATING 

829 share['host'] = None 

830 

831 self.assertSubDictMatch(share_data, 

832 db_api.share_create.call_args[0][1]) 

833 

834 @ddt.data( 

835 {'get_all_azs_return': [], 'subnet_by_az_side_effect': []}, 

836 {'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'}], 

837 'subnet_by_az_side_effect': [None]}, 

838 {'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'}], 

839 'subnet_by_az_side_effect': ['fake_sns_1']}, 

840 {'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'}, 

841 {'name': 'az2', 'id': 'az_id_2'}], 

842 'subnet_by_az_side_effect': [None, 'fake_sns_2']} 

843 ) 

844 @ddt.unpack 

845 def test__get_all_availability_zones_with_subnets( 

846 self, get_all_azs_return, subnet_by_az_side_effect): 

847 fake_share_network_id = 'fake_sn_id' 

848 self.mock_object(db_api, 'availability_zone_get_all', 

849 mock.Mock(return_value=get_all_azs_return)) 

850 self.mock_object( 

851 db_api, 'share_network_subnets_get_all_by_availability_zone_id', 

852 mock.Mock(side_effect=subnet_by_az_side_effect)) 

853 expected_az_names = ([], {}) 

854 expected_get_az_calls = [] 

855 for index, value in enumerate(get_all_azs_return): 

856 expected_get_az_calls.append(mock.call( 

857 self.context, share_network_id=fake_share_network_id, 

858 availability_zone_id=value['id'])) 

859 if subnet_by_az_side_effect[index] is not None: 

860 expected_az_names = ([value['name']], {value['id']: True}) 

861 

862 get_all_subnets = self.api._get_all_availability_zones_with_subnets 

863 compatible_azs = get_all_subnets(self.context, fake_share_network_id) 

864 

865 db_api.availability_zone_get_all.assert_called_once_with( 

866 self.context) 

867 db_get_azs_with_subnet = ( 

868 db_api.share_network_subnets_get_all_by_availability_zone_id) 

869 db_get_azs_with_subnet.assert_has_calls(expected_get_az_calls) 

870 

871 self.assertEqual(expected_az_names, compatible_azs) 

872 

873 def test_create_share_with_share_type_size_limit(self): 

874 self.assertRaises(exception.InvalidInput, 

875 self.api.create, 

876 self.context, 

877 'nfs', 

878 1, 

879 'display_name', 

880 'display_description', 

881 share_type=self.sized_sha_type) 

882 self.assertRaises(exception.InvalidInput, 

883 self.api.create, 

884 self.context, 

885 'nfs', 

886 5, 

887 'display_name', 

888 'display_description', 

889 share_type=self.sized_sha_type) 

890 

891 @ddt.data( 

892 {'availability_zones': None, 'compatible_azs_name': ['fake_az_1'], 

893 'compatible_azs_multiple': {}}, 

894 {'availability_zones': ['fake_az_2'], 

895 'compatible_azs_name': ['fake_az_2'], 'compatible_azs_multiple': {}}, 

896 {'availability_zones': ['fake_az_1', 'faze_az_2', 'fake_az_3'], 

897 'compatible_azs_name': ['fake_az_3'], 

898 'compatible_azs_multiple': {'fake_az_3': 1}} 

899 ) 

900 @ddt.unpack 

901 def test_create_share_with_subnets(self, availability_zones, 

902 compatible_azs_name, 

903 compatible_azs_multiple): 

904 share, share_data = self._setup_create_mocks() 

905 reservation = 'fake' 

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

907 mock.Mock(return_value=reservation)) 

908 self.mock_object(self.api, '_get_all_availability_zones_with_subnets', 

909 mock.Mock(return_value=[compatible_azs_name, 

910 compatible_azs_multiple])) 

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

912 self.mock_object(self.api, 'create_instance') 

913 self.mock_object(db_api, 'share_get') 

914 fake_share_network_id = 'fake_sn_id' 

915 

916 if availability_zones: 

917 expected_azs = ( 

918 [az for az in availability_zones if az in compatible_azs_name]) 

919 else: 

920 expected_azs = compatible_azs_name 

921 

922 az_multiple_sn_support_map = None 

923 if compatible_azs_multiple != {}: 

924 az_multiple_sn_support_map = compatible_azs_multiple 

925 

926 self.api.create( 

927 self.context, 

928 share_data['share_proto'], 

929 share_data['size'], 

930 share_data['display_name'], 

931 share_data['display_description'], 

932 share_network_id=fake_share_network_id, 

933 availability_zones=availability_zones, 

934 az_request_multiple_subnet_support_map=az_multiple_sn_support_map) 

935 share['status'] = constants.STATUS_CREATING 

936 share['host'] = None 

937 

938 quota.QUOTAS.reserve.assert_called_once() 

939 get_all_azs_sns = self.api._get_all_availability_zones_with_subnets 

940 get_all_azs_sns.assert_called_once_with( 

941 self.context, fake_share_network_id) 

942 quota.QUOTAS.commit.assert_called_once() 

943 self.api.create_instance.assert_called_once_with( 

944 self.context, share, share_network_id=fake_share_network_id, 

945 host=None, availability_zone=None, share_group=None, 

946 share_group_snapshot_member=None, share_type_id=None, 

947 availability_zones=expected_azs, 

948 az_request_multiple_subnet_support_map=compatible_azs_multiple, 

949 snapshot_host=None, 

950 scheduler_hints=None, mount_point_name=None, 

951 encryption_key_ref=None, 

952 ) 

953 db_api.share_get.assert_called_once() 

954 

955 @ddt.data( 

956 {'availability_zones': None, 'compatible_azs_name': [], 

957 'compatible_azs_multiple': []}, 

958 {'availability_zones': ['fake_az_1'], 

959 'compatible_azs_name': ['fake_az_2'], 'compatible_azs_multiple': []} 

960 ) 

961 @ddt.unpack 

962 def test_create_share_with_subnets_invalid_azs(self, availability_zones, 

963 compatible_azs_name, 

964 compatible_azs_multiple): 

965 share, share_data = self._setup_create_mocks() 

966 reservation = 'fake' 

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

968 mock.Mock(return_value=reservation)) 

969 self.mock_object(self.api, '_get_all_availability_zones_with_subnets', 

970 mock.Mock(return_value=[compatible_azs_name, 

971 compatible_azs_multiple])) 

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

973 self.mock_object(self.api, 'create_instance') 

974 self.mock_object(db_api, 'share_get') 

975 fake_share_network_id = 'fake_sn_id' 

976 

977 self.assertRaises( 

978 exception.InvalidInput, 

979 self.api.create, 

980 self.context, share_data['share_proto'], share_data['size'], 

981 share_data['display_name'], share_data['display_description'], 

982 share_network_id=fake_share_network_id, 

983 availability_zones=availability_zones) 

984 

985 quota.QUOTAS.reserve.assert_called_once() 

986 get_all_azs_sns = self.api._get_all_availability_zones_with_subnets 

987 get_all_azs_sns.assert_called_once_with( 

988 self.context, fake_share_network_id) 

989 

990 def test_prefix_with_missing_extra_spec_mount_point_name_support(self): 

991 share, share_data = self._setup_create_mocks(is_public=True) 

992 az = share_data.pop('availability_zone') 

993 extra_specs = {'replication_type': 'readable', 

994 'mount_point_name_support': False} 

995 self.mock_object( 

996 self.api, 'get_share_attributes_from_share_type', 

997 mock.Mock(return_value=extra_specs)) 

998 

999 self.assertRaises( 

1000 exception.InvalidInput, 

1001 self.api.create, 

1002 self.context, share_data['share_proto'], share_data['size'], 

1003 share_data['display_name'], share_data['display_description'], 

1004 availability_zones=az, 

1005 mount_point_name='fake_mp') 

1006 

1007 def test_configure_default_prefix(self): 

1008 share_type = {'extra_specs': {}} 

1009 conf = dict(DEFAULT=dict(default_mount_point_prefix="manila_")) 

1010 with test_utils.create_temp_config_with_opts(conf): 

1011 self.context.project_id = 'project_id' 

1012 mount_point_name = 'mount_point' 

1013 result = self.api._prefix_mount_point_name( 

1014 share_type, self.context, mount_point_name 

1015 ) 

1016 self.assertEqual(result, 'manila_mount_point') 

1017 

1018 def test_configure_empty_default_prefix(self): 

1019 share_type = {'extra_specs': {}} 

1020 conf = dict(DEFAULT=dict(default_mount_point_prefix="")) 

1021 with test_utils.create_temp_config_with_opts(conf): 

1022 self.context.project_id = 'project_id' 

1023 mount_point_name = 'mount_point' 

1024 result = self.api._prefix_mount_point_name( 

1025 share_type, self.context, mount_point_name 

1026 ) 

1027 self.assertEqual(result, 'mount_point') 

1028 

1029 def test_prefix_with_valid_mount_point_name(self): 

1030 share_type = { 

1031 'extra_specs': { 

1032 constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX: 

1033 'prefix_', 

1034 } 

1035 } 

1036 self.context.project_id = 'project_id' 

1037 mount_point_name = 'mount_point' 

1038 result = self.api._prefix_mount_point_name( 

1039 share_type, self.context, mount_point_name 

1040 ) 

1041 self.assertEqual(result, 'prefix_mount_point') 

1042 

1043 def test_empty_prefix_with_valid_mount_point_name(self): 

1044 share_type = { 

1045 'extra_specs': { 

1046 constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX: '', 

1047 } 

1048 } 

1049 self.context.project_id = 'project_id' 

1050 mount_point_name = 'mount_point' 

1051 result = self.api._prefix_mount_point_name( 

1052 share_type, self.context, mount_point_name 

1053 ) 

1054 self.assertEqual(result, 'mount_point') 

1055 

1056 def test_prefix_with_valid_missing_extra_spec_mount_point_name(self): 

1057 share_type = { 

1058 'extra_specs': {}, 

1059 } 

1060 self.context.project_id = 'project_id' 

1061 mount_point_name = 'mount_point' 

1062 result = self.api._prefix_mount_point_name( 

1063 share_type, self.context, mount_point_name 

1064 ) 

1065 self.assertEqual(result, 'project_id_mount_point') 

1066 

1067 def test_prefix_with_invalid_mount_point_name(self): 

1068 share_type = \ 

1069 { 

1070 'extra_specs': 

1071 { 

1072 constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX: 

1073 'prefix', 

1074 } 

1075 } 

1076 self.context.project_id = 'project_id' 

1077 mount_point_name = 'invalid*name' 

1078 self.assertRaises( 

1079 exception.InvalidInput, 

1080 self.api._prefix_mount_point_name, 

1081 share_type, 

1082 self.context, 

1083 mount_point_name 

1084 ) 

1085 

1086 def test_prefix_with_too_long_mount_point_name(self): 

1087 share_type = \ 

1088 { 

1089 'extra_specs': 

1090 { 

1091 constants.ExtraSpecs.PROVISIONING_MOUNT_POINT_PREFIX: 

1092 'prefix', 

1093 } 

1094 } 

1095 self.context.project_id = 'project_id' 

1096 mount_point_name = 'a' * 256 

1097 self.assertRaises( 

1098 exception.InvalidInput, 

1099 self.api._prefix_mount_point_name, 

1100 share_type, 

1101 self.context, 

1102 mount_point_name 

1103 ) 

1104 

1105 @ddt.data( 

1106 None, '', 'fake', 'nfsfake', 'cifsfake', 'glusterfsfake', 'hdfsfake') 

1107 def test_create_share_invalid_protocol(self, proto): 

1108 share, share_data = self._setup_create_mocks(protocol=proto) 

1109 

1110 all_protos = ','.join( 

1111 proto for proto in constants.SUPPORTED_SHARE_PROTOCOLS) 

1112 data = dict(DEFAULT=dict(enabled_share_protocols=all_protos)) 

1113 with test_utils.create_temp_config_with_opts(data): 

1114 self.assertRaises( 

1115 exception.InvalidInput, 

1116 self.api.create, 

1117 self.context, proto, share_data['size'], 

1118 share_data['display_name'], 

1119 share_data['display_description']) 

1120 

1121 @ddt.data({'overs': {'gigabytes': 'fake'}, 

1122 'expected_exception': exception.ShareSizeExceedsAvailableQuota, 

1123 'replication_type': None}, 

1124 {'overs': {'shares': 'fake'}, 

1125 'expected_exception': exception.ShareLimitExceeded, 

1126 'replication_type': None}, 

1127 {'overs': {'replica_gigabytes': 'fake'}, 

1128 'expected_exception': 

1129 exception.ShareReplicaSizeExceedsAvailableQuota, 

1130 'replication_type': constants.REPLICATION_TYPE_READABLE}, 

1131 {'overs': {'share_replicas': 'fake'}, 

1132 'expected_exception': exception.ShareReplicasLimitExceeded, 

1133 'replication_type': constants.REPLICATION_TYPE_READABLE}) 

1134 @ddt.unpack 

1135 def test_create_share_over_quota(self, overs, expected_exception, 

1136 replication_type): 

1137 extra_specs = {'replication_type': replication_type} 

1138 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

1139 share_type = db_api.share_type_get(self.context, share_type['id']) 

1140 share, share_data = self._setup_create_mocks( 

1141 share_type_id=share_type['id']) 

1142 

1143 az = share_data.pop('availability_zone') 

1144 

1145 usages = {'gigabytes': {'reserved': 5, 'in_use': 5}, 

1146 'shares': {'reserved': 10, 'in_use': 10}, 

1147 'replica_gigabytes': {'reserved': 5, 'in_use': 5}, 

1148 'share_replicas': {'reserved': 10, 'in_use': 10}} 

1149 

1150 quotas = {'gigabytes': 5, 'shares': 10, 

1151 'replica_gigabytes': 5, 'share_replicas': 10} 

1152 

1153 exc = exception.OverQuota(overs=overs, usages=usages, quotas=quotas) 

1154 self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc)) 

1155 

1156 if replication_type: 

1157 # Prevent the raising of an exception, to force the call to the 

1158 # function check_if_replica_quotas_exceeded 

1159 self.mock_object(self.api, 'check_if_share_quotas_exceeded') 

1160 

1161 self.assertRaises( 

1162 expected_exception, 

1163 self.api.create, 

1164 self.context, 

1165 share_data['share_proto'], 

1166 share_data['size'], 

1167 share_data['display_name'], 

1168 share_data['display_description'], 

1169 availability_zone=az, 

1170 share_type=share_type 

1171 ) 

1172 

1173 if replication_type: 

1174 quota.QUOTAS.reserve.assert_called_once_with( 

1175 self.context, share_type_id=share_type['id'], 

1176 gigabytes=1, shares=1, share_replicas=1, replica_gigabytes=1) 

1177 else: 

1178 quota.QUOTAS.reserve.assert_called_once_with( 

1179 self.context, share_type_id=share_type['id'], 

1180 shares=1, gigabytes=share_data['size']) 

1181 

1182 @ddt.data({'overs': {'per_share_gigabytes': 'fake'}, 

1183 'expected_exception': exception.ShareSizeExceedsLimit}) 

1184 @ddt.unpack 

1185 def test_create_share_over_per_share_quota(self, overs, 

1186 expected_exception): 

1187 share, share_data = self._setup_create_mocks() 

1188 

1189 quota.CONF.set_default("per_share_gigabytes", 5, 'quota') 

1190 share_data['size'] = 20 

1191 

1192 usages = {'per_share_gigabytes': {'reserved': 0, 'in_use': 0}} 

1193 quotas = {'per_share_gigabytes': 10} 

1194 exc = exception.OverQuota(overs=overs, usages=usages, quotas=quotas) 

1195 self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc)) 

1196 

1197 self.assertRaises( 

1198 expected_exception, 

1199 self.api.create, 

1200 self.context, 

1201 share_data['share_proto'], 

1202 share_data['size'], 

1203 share_data['display_name'], 

1204 share_data['display_description'] 

1205 ) 

1206 

1207 @ddt.data( 

1208 {'overs': {'encryption_keys': 'fake'}, 

1209 'expected_exception': ( 

1210 exception.EncryptionKeysLimitExceeded) 

1211 }) 

1212 @ddt.unpack 

1213 def test_create_share_over_encryption_keys_quota(self, overs, 

1214 expected_exception): 

1215 share, share_data = self._setup_create_mocks() 

1216 quota.CONF.set_default("encryption_keys", 2, 'quota') 

1217 share_data['encryption_key_ref'] = uuidutils.generate_uuid() 

1218 

1219 usages = {'encryption_keys': {'reserved': 0, 'in_use': 2}} 

1220 quotas = {'encryption_keys': 2} 

1221 exc = exception.OverQuota(overs=overs, usages=usages, quotas=quotas) 

1222 self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc)) 

1223 self.mock_object(db_api, 'share_server_get_all_with_filters', 

1224 mock.Mock(return_value={})) 

1225 self.mock_object(barbican_api, 'create_secret_access') 

1226 self.mock_object(db_api, 'encryption_keys_get_count', 

1227 mock.Mock(return_value=2)) 

1228 self.assertRaises( 

1229 expected_exception, 

1230 self.api.create, 

1231 self.context, 

1232 share_data['share_proto'], 

1233 share_data['size'], 

1234 share_data['display_name'], 

1235 share_data['display_description'], 

1236 encryption_key_ref=share_data['encryption_key_ref'] 

1237 ) 

1238 

1239 @ddt.data(exception.QuotaError, exception.InvalidShare) 

1240 def test_create_share_error_on_quota_commit(self, expected_exception): 

1241 share, share_data = self._setup_create_mocks() 

1242 reservation = 'fake' 

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

1244 mock.Mock(return_value=reservation)) 

1245 self.mock_object(quota.QUOTAS, 'commit', 

1246 mock.Mock(side_effect=expected_exception('fake'))) 

1247 self.mock_object(quota.QUOTAS, 'rollback') 

1248 self.mock_object(db_api, 'share_delete') 

1249 

1250 self.assertRaises( 

1251 expected_exception, 

1252 self.api.create, 

1253 self.context, 

1254 share_data['share_proto'], 

1255 share_data['size'], 

1256 share_data['display_name'], 

1257 share_data['display_description'] 

1258 ) 

1259 

1260 quota.QUOTAS.rollback.assert_called_once_with( 

1261 self.context, reservation, share_type_id=None) 

1262 db_api.share_delete.assert_called_once_with(self.context, share['id']) 

1263 

1264 def test_create_share_instance_with_host_and_az(self): 

1265 host, share, share_instance = self._setup_create_instance_mocks() 

1266 

1267 self.api.create_instance(self.context, share, host=host, 

1268 availability_zone='fake', 

1269 share_type_id='fake_share_type') 

1270 

1271 db_api.share_instance_create.assert_called_once_with( 

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

1273 { 

1274 'share_network_id': None, 

1275 'status': constants.STATUS_CREATING, 

1276 'scheduled_at': self.dt_utc, 

1277 'host': host, 

1278 'availability_zone_id': 'fake_id', 

1279 'share_type_id': 'fake_share_type', 

1280 'cast_rules_to_readonly': False, 

1281 'mount_point_name': None, 

1282 'encryption_key_ref': None 

1283 } 

1284 ) 

1285 db_api.share_type_get.assert_called_once_with( 

1286 self.context, share_instance['share_type_id']) 

1287 self.api.share_rpcapi.create_share_instance.assert_called_once_with( 

1288 self.context, 

1289 share_instance, 

1290 host, 

1291 request_spec=mock.ANY, 

1292 filter_properties={'scheduler_hints': None}, 

1293 snapshot_id=share['snapshot_id'], 

1294 ) 

1295 self.assertFalse( 

1296 self.api.scheduler_rpcapi.create_share_instance.called) 

1297 

1298 def test_create_share_instance_with_mount_point_name(self): 

1299 host, share, share_instance = self._setup_create_instance_mocks() 

1300 

1301 self.api.create_instance(self.context, share, host=host, 

1302 availability_zone='fake', 

1303 share_type_id='fake_share_type', 

1304 mount_point_name='fake_mp') 

1305 

1306 db_api.share_instance_create.assert_called_once_with( 

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

1308 { 

1309 'share_network_id': None, 

1310 'status': constants.STATUS_CREATING, 

1311 'scheduled_at': self.dt_utc, 

1312 'host': host, 

1313 'availability_zone_id': 'fake_id', 

1314 'share_type_id': 'fake_share_type', 

1315 'cast_rules_to_readonly': False, 

1316 'mount_point_name': 'fake_mp', 

1317 'encryption_key_ref': None 

1318 } 

1319 ) 

1320 

1321 def test_create_share_instance_without_host(self): 

1322 _, share, share_instance = self._setup_create_instance_mocks() 

1323 

1324 self.api.create_instance(self.context, share) 

1325 

1326 (self.api.scheduler_rpcapi.create_share_instance. 

1327 assert_called_once_with( 

1328 self.context, request_spec=mock.ANY, 

1329 filter_properties={'scheduler_hints': None})) 

1330 self.assertFalse(self.api.share_rpcapi.create_share_instance.called) 

1331 

1332 def test_create_share_instance_from_snapshot(self): 

1333 snapshot, share, _, _ = self._setup_create_from_snapshot_mocks() 

1334 

1335 request_spec, share_instance = ( 

1336 self.api.create_share_instance_and_get_request_spec( 

1337 self.context, share) 

1338 ) 

1339 

1340 self.assertIsNotNone(share_instance) 

1341 self.assertEqual(share['id'], 

1342 request_spec['share_instance_properties']['share_id']) 

1343 self.assertEqual(share['snapshot_id'], request_spec['snapshot_id']) 

1344 

1345 self.assertFalse( 

1346 self.api.share_rpcapi.create_share_instance_and_get_request_spec 

1347 .called) 

1348 

1349 def test_create_instance_share_group_snapshot_member(self): 

1350 fake_req_spec = { 

1351 'share_properties': 'fake_share_properties', 

1352 'share_instance_properties': 'fake_share_instance_properties', 

1353 } 

1354 share = fakes.fake_share() 

1355 member_info = { 

1356 'host': 'host', 

1357 'share_network_id': 'share_network_id', 

1358 'share_server_id': 'share_server_id', 

1359 } 

1360 

1361 fake_instance = fakes.fake_share_instance( 

1362 share_id=share['id'], **member_info) 

1363 sg_snap_member = {'share_instance': fake_instance} 

1364 self.mock_policy_check = self.mock_object( 

1365 policy, 'check_policy', mock.Mock(return_value=True)) 

1366 mock_share_rpcapi_call = self.mock_object(self.share_rpcapi, 

1367 'create_share_instance') 

1368 mock_scheduler_rpcapi_call = self.mock_object(self.scheduler_rpcapi, 

1369 'create_share_instance') 

1370 mock_db_share_instance_update = self.mock_object( 

1371 db_api, 'share_instance_update') 

1372 self.mock_object( 

1373 share_api.API, 'create_share_instance_and_get_request_spec', 

1374 mock.Mock(return_value=(fake_req_spec, fake_instance))) 

1375 

1376 retval = self.api.create_instance( 

1377 self.context, fakes.fake_share(), 

1378 share_group_snapshot_member=sg_snap_member) 

1379 

1380 self.assertIsNone(retval) 

1381 mock_db_share_instance_update.assert_called_once_with( 

1382 self.context, fake_instance['id'], member_info) 

1383 self.assertFalse(mock_scheduler_rpcapi_call.called) 

1384 self.assertFalse(mock_share_rpcapi_call.called) 

1385 

1386 def test_get_share_attributes_from_share_type(self): 

1387 

1388 share_type = { 

1389 'extra_specs': { 

1390 'snapshot_support': True, 

1391 'create_share_from_snapshot_support': False, 

1392 'revert_to_snapshot_support': False, 

1393 'mount_snapshot_support': False, 

1394 'mount_point_name_support': False, 

1395 'replication_type': 'dr', 

1396 } 

1397 } 

1398 

1399 result = self.api.get_share_attributes_from_share_type(share_type) 

1400 

1401 self.assertEqual(share_type['extra_specs'], result) 

1402 

1403 @ddt.data({}, {'extra_specs': {}}, None) 

1404 def test_get_share_attributes_from_share_type_defaults(self, share_type): 

1405 

1406 result = self.api.get_share_attributes_from_share_type(share_type) 

1407 

1408 expected = { 

1409 'snapshot_support': False, 

1410 'create_share_from_snapshot_support': False, 

1411 'revert_to_snapshot_support': False, 

1412 'mount_snapshot_support': False, 

1413 'mount_point_name_support': False, 

1414 'replication_type': None, 

1415 } 

1416 self.assertEqual(expected, result) 

1417 

1418 @ddt.data({'extra_specs': {'snapshot_support': 'fake'}}, 

1419 {'extra_specs': {'create_share_from_snapshot_support': 'fake'}}) 

1420 def test_get_share_attributes_from_share_type_invalid(self, share_type): 

1421 

1422 self.assertRaises(exception.InvalidExtraSpec, 

1423 self.api.get_share_attributes_from_share_type, 

1424 share_type) 

1425 

1426 @ddt.data( 

1427 {'replication_type': 'dr', 'dhss': False, 'share_server_id': None}, 

1428 {'replication_type': 'readable', 'dhss': False, 

1429 'share_server_id': None}, 

1430 {'replication_type': None, 'dhss': False, 'share_server_id': None}, 

1431 {'replication_type': None, 'dhss': True, 'share_server_id': 'fake'} 

1432 ) 

1433 @ddt.unpack 

1434 def test_manage_new(self, replication_type, dhss, share_server_id): 

1435 share_data = { 

1436 'host': 'fake', 

1437 'export_location_path': 'fake', 

1438 'share_proto': 'fake', 

1439 'share_type_id': 'fake', 

1440 } 

1441 if dhss: 

1442 share_data['share_server_id'] = share_server_id 

1443 driver_options = {} 

1444 date = datetime.datetime(1, 1, 1, 1, 1, 1) 

1445 timeutils.utcnow.return_value = date 

1446 fake_subnet = db_utils.create_share_network_subnet( 

1447 share_network_id='fake') 

1448 share_server = db_utils.create_share_server( 

1449 status=constants.STATUS_ACTIVE, id=share_server_id, 

1450 share_network_subnets=[fake_subnet]) 

1451 share_network = db_utils.create_share_network(id='fake') 

1452 fake_share_data = { 

1453 'id': 'fakeid', 

1454 'status': constants.STATUS_CREATING, 

1455 } 

1456 fake_type = { 

1457 'id': 'fake_type_id', 

1458 'extra_specs': { 

1459 'snapshot_support': False, 

1460 'replication_type': replication_type, 

1461 'create_share_from_snapshot_support': False, 

1462 'revert_to_snapshot_support': False, 

1463 'mount_snapshot_support': False, 

1464 'mount_point_name_support': False, 

1465 'driver_handles_share_servers': dhss, 

1466 }, 

1467 } 

1468 

1469 share = db_api.share_create(self.context, fake_share_data) 

1470 

1471 self.mock_object(self.scheduler_rpcapi, 'manage_share') 

1472 self.mock_object(db_api, 'share_create', 

1473 mock.Mock(return_value=share)) 

1474 self.mock_object(db_api, 'export_locations_update') 

1475 self.mock_object(db_api, 'share_get', 

1476 mock.Mock(return_value=share)) 

1477 self.mock_object(share_types, 'get_share_type', 

1478 mock.Mock(return_value=fake_type)) 

1479 self.mock_object(db_api, 'share_server_get', 

1480 mock.Mock(return_value=share_server)) 

1481 self.mock_object(db_api, 'share_instance_get_all', 

1482 mock.Mock(return_value=[])) 

1483 self.mock_object(db_api, 'share_network_get', 

1484 mock.Mock(return_value=share_network)) 

1485 

1486 self.api.manage(self.context, copy.deepcopy(share_data), 

1487 driver_options) 

1488 

1489 share_data.update({ 

1490 'user_id': self.context.user_id, 

1491 'project_id': self.context.project_id, 

1492 'status': constants.STATUS_MANAGING, 

1493 'scheduled_at': date, 

1494 'snapshot_support': fake_type['extra_specs']['snapshot_support'], 

1495 'create_share_from_snapshot_support': 

1496 fake_type['extra_specs']['create_share_from_snapshot_support'], 

1497 'revert_to_snapshot_support': 

1498 fake_type['extra_specs']['revert_to_snapshot_support'], 

1499 'mount_snapshot_support': 

1500 fake_type['extra_specs']['mount_snapshot_support'], 

1501 'mount_point_name_support': 

1502 fake_type['extra_specs']['mount_point_name_support'], 

1503 'replication_type': replication_type, 

1504 }) 

1505 

1506 expected_request_spec = self._get_request_spec_dict( 

1507 share, fake_type, self.context, size=0, 

1508 share_proto=share_data['share_proto'], 

1509 host=share_data['host']) 

1510 

1511 if dhss: 

1512 share_data.update({ 

1513 'share_network_id': fake_subnet['share_network_id']}) 

1514 export_location = share_data.pop('export_location_path') 

1515 filters = {'export_location_path': export_location, 

1516 'host': share_data['host'] 

1517 } 

1518 if share_server_id: 

1519 filters['share_server_id'] = share_server_id 

1520 db_api.share_instance_get_all.assert_called_once_with( 

1521 self.context, filters=filters) 

1522 db_api.share_create.assert_called_once_with(self.context, share_data) 

1523 db_api.share_get.assert_called_once_with(self.context, share['id']) 

1524 db_api.export_locations_update.assert_called_once_with( 

1525 self.context, share.instance['id'], export_location) 

1526 self.scheduler_rpcapi.manage_share.assert_called_once_with( 

1527 self.context, share['id'], driver_options, expected_request_spec) 

1528 if dhss: 

1529 db_api.share_server_get.assert_called_once_with( 

1530 self.context, share_data['share_server_id']) 

1531 

1532 @ddt.data((True, exception.InvalidInput, True), 

1533 (True, exception.InvalidInput, False), 

1534 (False, exception.InvalidInput, True), 

1535 (True, exception.InvalidInput, True)) 

1536 @ddt.unpack 

1537 def test_manage_new_dhss_true_and_false(self, dhss, exception_type, 

1538 has_share_server_id): 

1539 share_data = { 

1540 'host': 'fake', 

1541 'export_location_path': 'fake', 

1542 'share_proto': 'fake', 

1543 'share_type_id': 'fake', 

1544 } 

1545 if has_share_server_id: 

1546 share_data['share_server_id'] = 'fake' 

1547 

1548 driver_options = {} 

1549 date = datetime.datetime(1, 1, 1, 1, 1, 1) 

1550 timeutils.utcnow.return_value = date 

1551 fake_type = { 

1552 'id': 'fake_type_id', 

1553 'extra_specs': { 

1554 'snapshot_support': False, 

1555 'create_share_from_snapshot_support': False, 

1556 'revert_to_snapshot_support': False, 

1557 'mount_snapshot_support': False, 

1558 'mount_point_name_support': False, 

1559 'driver_handles_share_servers': dhss, 

1560 }, 

1561 } 

1562 

1563 self.mock_object(share_types, 'get_share_type', 

1564 mock.Mock(return_value=fake_type)) 

1565 self.mock_object(db_api, 'share_instance_get_all', 

1566 mock.Mock(return_value=[])) 

1567 

1568 self.assertRaises(exception_type, 

1569 self.api.manage, 

1570 self.context, 

1571 share_data=share_data, 

1572 driver_options=driver_options 

1573 ) 

1574 share_types.get_share_type.assert_called_once_with( 

1575 self.context, share_data['share_type_id'] 

1576 ) 

1577 filters = {'export_location_path': share_data['export_location_path'], 

1578 'host': share_data['host'] 

1579 } 

1580 if has_share_server_id: 

1581 filters['share_server_id'] = 'fake' 

1582 db_api.share_instance_get_all.assert_called_once_with( 

1583 self.context, filters=filters) 

1584 

1585 def test_manage_new_share_server_not_found(self): 

1586 share_data = { 

1587 'host': 'fake', 

1588 'export_location_path': 'fake', 

1589 'share_proto': 'fake', 

1590 'share_type_id': 'fake', 

1591 'share_server_id': 'fake' 

1592 

1593 } 

1594 driver_options = {} 

1595 date = datetime.datetime(1, 1, 1, 1, 1, 1) 

1596 timeutils.utcnow.return_value = date 

1597 

1598 fake_type = { 

1599 'id': 'fake_type_id', 

1600 'extra_specs': { 

1601 'snapshot_support': False, 

1602 'replication_type': 'dr', 

1603 'create_share_from_snapshot_support': False, 

1604 'revert_to_snapshot_support': False, 

1605 'mount_snapshot_support': False, 

1606 'mount_point_name_support': False, 

1607 'driver_handles_share_servers': True, 

1608 }, 

1609 } 

1610 

1611 self.mock_object(share_types, 'get_share_type', 

1612 mock.Mock(return_value=fake_type)) 

1613 self.mock_object(db_api, 'share_instance_get_all', 

1614 mock.Mock(return_value=[])) 

1615 

1616 self.assertRaises(exception.InvalidInput, 

1617 self.api.manage, 

1618 self.context, 

1619 share_data=share_data, 

1620 driver_options=driver_options 

1621 ) 

1622 share_types.get_share_type.assert_called_once_with( 

1623 self.context, share_data['share_type_id'] 

1624 ) 

1625 db_api.share_instance_get_all.assert_called_once_with( 

1626 self.context, filters={ 

1627 'export_location_path': share_data['export_location_path'], 

1628 'host': share_data['host'], 

1629 'share_server_id': share_data['share_server_id'] 

1630 } 

1631 ) 

1632 

1633 def test_manage_new_share_server_not_active(self): 

1634 share_data = { 

1635 'host': 'fake', 

1636 'export_location_path': 'fake', 

1637 'share_proto': 'fake', 

1638 'share_type_id': 'fake', 

1639 'share_server_id': 'fake' 

1640 

1641 } 

1642 fake_share_data = { 

1643 'id': 'fakeid', 

1644 'status': constants.STATUS_ERROR, 

1645 } 

1646 driver_options = {} 

1647 date = datetime.datetime(1, 1, 1, 1, 1, 1) 

1648 timeutils.utcnow.return_value = date 

1649 

1650 fake_type = { 

1651 'id': 'fake_type_id', 

1652 'extra_specs': { 

1653 'snapshot_support': False, 

1654 'replication_type': 'dr', 

1655 'create_share_from_snapshot_support': False, 

1656 'revert_to_snapshot_support': False, 

1657 'mount_snapshot_support': False, 

1658 'mount_point_name_support': False, 

1659 'driver_handles_share_servers': True, 

1660 }, 

1661 } 

1662 

1663 share = db_api.share_create(self.context, fake_share_data) 

1664 

1665 self.mock_object(share_types, 'get_share_type', 

1666 mock.Mock(return_value=fake_type)) 

1667 self.mock_object(db_api, 'share_instance_get_all', 

1668 mock.Mock(return_value=[])) 

1669 self.mock_object(db_api, 'share_server_get', 

1670 mock.Mock(return_value=share)) 

1671 

1672 self.assertRaises(exception.InvalidShareServer, 

1673 self.api.manage, 

1674 self.context, 

1675 share_data=share_data, 

1676 driver_options=driver_options 

1677 ) 

1678 share_types.get_share_type.assert_called_once_with( 

1679 self.context, share_data['share_type_id'] 

1680 ) 

1681 db_api.share_instance_get_all.assert_called_once_with( 

1682 self.context, filters={ 

1683 'export_location_path': share_data['export_location_path'], 

1684 'host': share_data['host'], 

1685 'share_server_id': share_data['share_server_id'] 

1686 } 

1687 ) 

1688 db_api.share_server_get.assert_called_once_with( 

1689 self.context, share_data['share_server_id'] 

1690 ) 

1691 

1692 @ddt.data(constants.STATUS_MANAGE_ERROR, constants.STATUS_AVAILABLE) 

1693 def test_manage_duplicate(self, status): 

1694 share_data = { 

1695 'host': 'fake', 

1696 'export_location_path': 'fake', 

1697 'share_proto': 'fake', 

1698 'share_type_id': 'fake', 

1699 } 

1700 driver_options = {} 

1701 fake_type = { 

1702 'id': 'fake_type_id', 

1703 'extra_specs': { 

1704 'snapshot_support': False, 

1705 'create_share_from_snapshot_support': False, 

1706 'driver_handles_share_servers': False, 

1707 }, 

1708 } 

1709 already_managed = [{'id': 'fake', 'status': status}] 

1710 self.mock_object(db_api, 'share_instance_get_all', 

1711 mock.Mock(return_value=already_managed)) 

1712 self.mock_object(share_types, 'get_share_type', 

1713 mock.Mock(return_value=fake_type)) 

1714 self.assertRaises(exception.InvalidShare, self.api.manage, 

1715 self.context, share_data, driver_options) 

1716 

1717 def _get_request_spec_dict(self, share, share_type, context, **kwargs): 

1718 

1719 if share is None: 1719 ↛ 1720line 1719 didn't jump to line 1720 because the condition on line 1719 was never true

1720 share = {'instance': {}} 

1721 

1722 share_instance = share['instance'] 

1723 

1724 share_properties = { 

1725 'size': kwargs.get('size', share.get('size')), 

1726 'user_id': kwargs.get('user_id', share.get('user_id')), 

1727 'project_id': kwargs.get('project_id', share.get('project_id')), 

1728 'metadata': db_api.share_metadata_get(context, share['id']), 

1729 'snapshot_support': kwargs.get( 

1730 'snapshot_support', 

1731 share_type['extra_specs']['snapshot_support']), 

1732 'create_share_from_snapshot_support': kwargs.get( 

1733 'create_share_from_snapshot_support', 

1734 share_type['extra_specs'].get( 

1735 'create_share_from_snapshot_support')), 

1736 'revert_to_snapshot_support': kwargs.get( 

1737 'revert_to_snapshot_support', 

1738 share_type['extra_specs'].get('revert_to_snapshot_support')), 

1739 'mount_snapshot_support': kwargs.get( 

1740 'mount_snapshot_support', 

1741 share_type['extra_specs'].get('mount_snapshot_support')), 

1742 'mount_point_name_support': kwargs.get( 

1743 'mount_point_name_support', 

1744 share_type['extra_specs'].get('mount_point_name_support')), 

1745 'share_proto': kwargs.get('share_proto', share.get('share_proto')), 

1746 'share_type_id': share_type['id'], 

1747 'is_public': kwargs.get('is_public', share.get('is_public')), 

1748 'share_group_id': kwargs.get( 

1749 'share_group_id', share.get('share_group_id')), 

1750 'source_share_group_snapshot_member_id': kwargs.get( 

1751 'source_share_group_snapshot_member_id', 

1752 share.get('source_share_group_snapshot_member_id')), 

1753 'snapshot_id': kwargs.get('snapshot_id', share.get('snapshot_id')), 

1754 } 

1755 share_instance_properties = { 

1756 'availability_zone_id': kwargs.get( 

1757 'availability_zone_id', 

1758 share_instance.get('availability_zone_id')), 

1759 'share_network_id': kwargs.get( 

1760 'share_network_id', share_instance.get('share_network_id')), 

1761 'share_server_id': kwargs.get( 

1762 'share_server_id', share_instance.get('share_server_id')), 

1763 'share_id': kwargs.get('share_id', share_instance.get('share_id')), 

1764 'host': kwargs.get('host', share_instance.get('host')), 

1765 'status': kwargs.get('status', share_instance.get('status')), 

1766 } 

1767 

1768 request_spec = { 

1769 'share_properties': share_properties, 

1770 'share_instance_properties': share_instance_properties, 

1771 'share_type': share_type, 

1772 'share_id': share.get('id'), 

1773 } 

1774 return request_spec 

1775 

1776 def test_unmanage(self): 

1777 

1778 share = db_utils.create_share( 

1779 id='fakeid', 

1780 host='fake', 

1781 size='1', 

1782 status=constants.STATUS_AVAILABLE, 

1783 user_id=self.context.user_id, 

1784 project_id=self.context.project_id, 

1785 task_state=None) 

1786 

1787 self.mock_object(db_api, 'share_update', mock.Mock()) 

1788 self.api.unmanage(self.context, share) 

1789 

1790 self.share_rpcapi.unmanage_share.assert_called_once_with( 

1791 self.context, mock.ANY) 

1792 db_api.share_update.assert_called_once_with( 

1793 mock.ANY, share['id'], mock.ANY) 

1794 

1795 def test_unmanage_task_state_busy(self): 

1796 

1797 share = db_utils.create_share( 

1798 id='fakeid', 

1799 host='fake', 

1800 size='1', 

1801 status=constants.STATUS_AVAILABLE, 

1802 user_id=self.context.user_id, 

1803 project_id=self.context.project_id, 

1804 task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS) 

1805 

1806 self.assertRaises(exception.ShareBusyException, self.api.unmanage, 

1807 self.context, share) 

1808 

1809 def test_unmanage_locked_share(self): 

1810 self.mock_object( 

1811 self.api.db, 

1812 'resource_lock_get_all', 

1813 mock.Mock(return_value=([{'id': 'l1'}, {'id': 'l2'}], None)) 

1814 ) 

1815 share = db_utils.create_share( 

1816 id='fakeid', 

1817 host='fake', 

1818 size='1', 

1819 status=constants.STATUS_AVAILABLE, 

1820 user_id=self.context.user_id, 

1821 project_id=self.context.project_id, 

1822 task_state=None) 

1823 self.mock_object(db_api, 'share_update', mock.Mock()) 

1824 

1825 self.assertRaises(exception.InvalidShare, 

1826 self.api.unmanage, 

1827 self.context, 

1828 share) 

1829 

1830 # lock check decorator executed first, nothing else is invoked 

1831 self.share_rpcapi.unmanage_share.assert_not_called() 

1832 db_api.share_update.assert_not_called() 

1833 

1834 @mock.patch.object(quota.QUOTAS, 'reserve', 

1835 mock.Mock(return_value='reservation')) 

1836 @mock.patch.object(quota.QUOTAS, 'commit', mock.Mock()) 

1837 def test_create_snapshot(self): 

1838 snapshot = db_utils.create_snapshot( 

1839 with_share=True, status=constants.STATUS_CREATING, size=1) 

1840 share = snapshot['share'] 

1841 

1842 fake_name = 'fakename' 

1843 fake_desc = 'fakedesc' 

1844 options = { 

1845 'share_id': share['id'], 

1846 'user_id': self.context.user_id, 

1847 'project_id': self.context.project_id, 

1848 'status': constants.STATUS_CREATING, 

1849 'progress': '0%', 

1850 'share_size': share['size'], 

1851 'size': 1, 

1852 'display_name': fake_name, 

1853 'display_description': fake_desc, 

1854 'share_proto': share['share_proto'], 

1855 } 

1856 with mock.patch.object(db_api, 'share_snapshot_create', 

1857 mock.Mock(return_value=snapshot)): 

1858 self.api.create_snapshot(self.context, share, fake_name, 

1859 fake_desc) 

1860 share_api.policy.check_policy.assert_called_once_with( 

1861 self.context, 'share', 'create_snapshot', share) 

1862 quota.QUOTAS.reserve.assert_called_once_with( 

1863 self.context, share_type_id=None, 

1864 snapshot_gigabytes=1, snapshots=1) 

1865 quota.QUOTAS.commit.assert_called_once_with( 

1866 self.context, 'reservation', share_type_id=None) 

1867 db_api.share_snapshot_create.assert_called_once_with( 

1868 self.context, options) 

1869 

1870 def test_create_snapshot_space_quota_exceeded(self): 

1871 

1872 share = fakes.fake_share( 

1873 id=uuidutils.generate_uuid(), size=1, project_id='fake_project', 

1874 user_id='fake_user', has_replicas=False, status='available') 

1875 usages = {'snapshot_gigabytes': {'reserved': 10, 'in_use': 0}} 

1876 quotas = {'snapshot_gigabytes': 10} 

1877 side_effect = exception.OverQuota( 

1878 overs='snapshot_gigabytes', usages=usages, quotas=quotas) 

1879 self.mock_object( 

1880 quota.QUOTAS, 'reserve', mock.Mock(side_effect=side_effect)) 

1881 mock_snap_create = self.mock_object(db_api, 'share_snapshot_create') 

1882 

1883 self.assertRaises(exception.SnapshotSizeExceedsAvailableQuota, 

1884 self.api.create_snapshot, 

1885 self.context, 

1886 share, 

1887 'fake_name', 

1888 'fake_description') 

1889 mock_snap_create.assert_not_called() 

1890 

1891 def test_create_snapshot_count_quota_exceeded(self): 

1892 

1893 share = fakes.fake_share( 

1894 id=uuidutils.generate_uuid(), size=1, project_id='fake_project', 

1895 user_id='fake_user', has_replicas=False, status='available') 

1896 usages = {'snapshots': {'reserved': 10, 'in_use': 0}} 

1897 quotas = {'snapshots': 10} 

1898 side_effect = exception.OverQuota( 

1899 overs='snapshots', usages=usages, quotas=quotas) 

1900 self.mock_object( 

1901 quota.QUOTAS, 'reserve', mock.Mock(side_effect=side_effect)) 

1902 mock_snap_create = self.mock_object(db_api, 'share_snapshot_create') 

1903 

1904 self.assertRaises(exception.SnapshotLimitExceeded, 

1905 self.api.create_snapshot, 

1906 self.context, 

1907 share, 

1908 'fake_name', 

1909 'fake_description') 

1910 mock_snap_create.assert_not_called() 

1911 

1912 def test_manage_snapshot_share_not_found(self): 

1913 snapshot = fakes.fake_snapshot(share_id='fake_share', 

1914 as_primitive=True) 

1915 mock_share_get_call = self.mock_object( 

1916 db_api, 'share_get', mock.Mock(side_effect=exception.NotFound)) 

1917 mock_db_snapshot_call = self.mock_object( 

1918 db_api, 'share_snapshot_get_all_for_share') 

1919 

1920 self.assertRaises(exception.ShareNotFound, 

1921 self.api.manage_snapshot, 

1922 self.context, 

1923 snapshot, 

1924 {}) 

1925 self.assertFalse(mock_db_snapshot_call.called) 

1926 mock_share_get_call.assert_called_once_with( 

1927 self.context, snapshot['share_id']) 

1928 

1929 def test_manage_snapshot_share_has_replicas(self): 

1930 share_ref = fakes.fake_share( 

1931 has_replicas=True, status=constants.STATUS_AVAILABLE) 

1932 self.mock_object( 

1933 db_api, 'share_get', mock.Mock(return_value=share_ref)) 

1934 snapshot = fakes.fake_snapshot(create_instance=True, as_primitive=True) 

1935 mock_db_snapshot_get_all_for_share_call = self.mock_object( 

1936 db_api, 'share_snapshot_get_all_for_share') 

1937 

1938 self.assertRaises(exception.InvalidShare, 

1939 self.api.manage_snapshot, 

1940 context, 

1941 snapshot, 

1942 {}) 

1943 self.assertFalse(mock_db_snapshot_get_all_for_share_call.called) 

1944 

1945 def test_manage_snapshot_already_managed(self): 

1946 share_ref = fakes.fake_share( 

1947 has_replicas=False, status=constants.STATUS_AVAILABLE) 

1948 snapshot = fakes.fake_snapshot(create_instance=True, as_primitive=True) 

1949 self.mock_object( 

1950 db_api, 'share_get', mock.Mock(return_value=share_ref)) 

1951 mock_db_snapshot_call = self.mock_object( 

1952 db_api, 'share_snapshot_get_all_for_share', mock.Mock( 

1953 return_value=[snapshot])) 

1954 mock_db_snapshot_create_call = self.mock_object( 

1955 db_api, 'share_snapshot_create') 

1956 

1957 self.assertRaises(exception.ManageInvalidShareSnapshot, 

1958 self.api.manage_snapshot, 

1959 self.context, 

1960 snapshot, 

1961 {}) 

1962 mock_db_snapshot_call.assert_called_once_with( 

1963 self.context, snapshot['share_id']) 

1964 self.assertFalse(mock_db_snapshot_create_call.called) 

1965 

1966 def test_manage_snapshot(self): 

1967 share_ref = fakes.fake_share( 

1968 has_replicas=False, status=constants.STATUS_AVAILABLE, 

1969 host='fake_host') 

1970 existing_snapshot = fakes.fake_snapshot( 

1971 create_instance=True, share_id=share_ref['id']) 

1972 self.mock_object(db_api, 'share_snapshot_get_all_for_share', 

1973 mock.Mock(return_value=[existing_snapshot])) 

1974 snapshot_data = { 

1975 'share_id': share_ref['id'], 

1976 'provider_location': 'someproviderlocation', 

1977 } 

1978 expected_snapshot_data = { 

1979 'user_id': self.context.user_id, 

1980 'project_id': self.context.project_id, 

1981 'status': constants.STATUS_MANAGING, 

1982 'share_size': share_ref['size'], 

1983 'progress': '0%', 

1984 'share_proto': share_ref['share_proto'], 

1985 } 

1986 expected_snapshot_data.update(**snapshot_data) 

1987 snapshot = fakes.fake_snapshot( 

1988 create_instance=True, **expected_snapshot_data) 

1989 self.mock_object( 

1990 db_api, 'share_get', mock.Mock(return_value=share_ref)) 

1991 mock_db_snapshot_create_call = self.mock_object( 

1992 db_api, 'share_snapshot_create', mock.Mock(return_value=snapshot)) 

1993 mock_rpc_call = self.mock_object(self.share_rpcapi, 'manage_snapshot', 

1994 mock.Mock(return_value=snapshot)) 

1995 

1996 new_snap = self.api.manage_snapshot( 

1997 self.context, snapshot_data, {}) 

1998 

1999 self.assertEqual(new_snap, snapshot) 

2000 mock_db_snapshot_create_call.assert_called_once_with( 

2001 self.context, expected_snapshot_data) 

2002 mock_rpc_call.assert_called_once_with( 

2003 self.context, snapshot, share_ref['host'], {}) 

2004 

2005 def test_manage_share_server(self): 

2006 """Tests manage share server""" 

2007 host = 'fake_host' 

2008 fake_share_network = { 

2009 'id': 'fake_net_id' 

2010 } 

2011 fake_share_net_subnet = [{ 

2012 'id': 'fake_subnet_id', 

2013 'share_network_id': fake_share_network['id'] 

2014 }] 

2015 identifier = 'fake_identifier' 

2016 values = { 

2017 'host': host, 

2018 'share_network_subnets': [fake_share_net_subnet], 

2019 'status': constants.STATUS_MANAGING, 

2020 'is_auto_deletable': False, 

2021 'identifier': identifier, 

2022 } 

2023 

2024 server_managing = { 

2025 'id': 'fake_server_id', 

2026 'status': constants.STATUS_MANAGING, 

2027 'host': host, 

2028 'share_network_subnets': [fake_share_net_subnet], 

2029 'is_auto_deletable': False, 

2030 'identifier': identifier, 

2031 } 

2032 

2033 mock_share_server_search = self.mock_object( 

2034 db_api, 'share_server_search_by_identifier', 

2035 mock.Mock(side_effect=exception.ShareServerNotFound('fake'))) 

2036 

2037 mock_share_server_get = self.mock_object( 

2038 db_api, 'share_server_get', 

2039 mock.Mock( 

2040 return_value=server_managing) 

2041 ) 

2042 mock_share_server_create = self.mock_object( 

2043 db_api, 'share_server_create', 

2044 mock.Mock(return_value=server_managing) 

2045 ) 

2046 result = self.api.manage_share_server( 

2047 self.context, 'fake_identifier', host, fake_share_net_subnet, 

2048 {'opt1': 'val1', 'opt2': 'val2'} 

2049 ) 

2050 

2051 mock_share_server_create.assert_called_once_with( 

2052 self.context, values) 

2053 

2054 mock_share_server_get.assert_called_once_with( 

2055 self.context, 'fake_server_id') 

2056 

2057 mock_share_server_search.assert_called_once_with( 

2058 self.context, 'fake_identifier') 

2059 

2060 result_dict = { 

2061 'host': result['host'], 

2062 'share_network_subnets': result['share_network_subnets'], 

2063 'status': result['status'], 

2064 'is_auto_deletable': result['is_auto_deletable'], 

2065 'identifier': result['identifier'], 

2066 } 

2067 self.assertEqual(values, result_dict) 

2068 

2069 def test_manage_share_server_invalid(self): 

2070 

2071 server = {'identifier': 'fake_server'} 

2072 

2073 mock_share_server_search = self.mock_object( 

2074 db_api, 'share_server_search_by_identifier', 

2075 mock.Mock(return_value=[server])) 

2076 

2077 self.assertRaises( 

2078 exception.InvalidInput, self.api.manage_share_server, 

2079 self.context, 'invalid_identifier', 'fake_host', 'fake_share_net', 

2080 {}) 

2081 

2082 mock_share_server_search.assert_called_once_with( 

2083 self.context, 'invalid_identifier') 

2084 

2085 def test_unmanage_snapshot(self): 

2086 fake_host = 'fake_host' 

2087 snapshot_data = { 

2088 'status': constants.STATUS_UNMANAGING, 

2089 'terminated_at': timeutils.utcnow(), 

2090 } 

2091 snapshot = fakes.fake_snapshot( 

2092 create_instance=True, share_instance_id='id2', **snapshot_data) 

2093 mock_db_snap_update_call = self.mock_object( 

2094 db_api, 'share_snapshot_update', mock.Mock(return_value=snapshot)) 

2095 mock_rpc_call = self.mock_object( 

2096 self.share_rpcapi, 'unmanage_snapshot') 

2097 

2098 retval = self.api.unmanage_snapshot( 

2099 self.context, snapshot, fake_host) 

2100 

2101 self.assertIsNone(retval) 

2102 mock_db_snap_update_call.assert_called_once_with( 

2103 self.context, snapshot['id'], snapshot_data) 

2104 mock_rpc_call.assert_called_once_with( 

2105 self.context, snapshot, fake_host) 

2106 

2107 def test_unmanage_share_server(self): 

2108 shr1 = {} 

2109 share_server = db_utils.create_share_server(**shr1) 

2110 update_data = {'status': constants.STATUS_UNMANAGING, 

2111 'terminated_at': timeutils.utcnow()} 

2112 

2113 mock_share_instance_get_all = self.mock_object( 

2114 db_api, 'share_instance_get_all_by_share_server', 

2115 mock.Mock(return_value={})) 

2116 mock_share_group_get_all = self.mock_object( 

2117 db_api, 'share_group_get_all_by_share_server', 

2118 mock.Mock(return_value={})) 

2119 mock_share_server_update = self.mock_object( 

2120 db_api, 'share_server_update', 

2121 mock.Mock(return_value=share_server)) 

2122 

2123 mock_rpc = self.mock_object( 

2124 self.api.share_rpcapi, 'unmanage_share_server') 

2125 

2126 self.api.unmanage_share_server(self.context, share_server, True) 

2127 

2128 mock_share_instance_get_all.assert_called_once_with( 

2129 self.context, share_server['id'] 

2130 ) 

2131 mock_share_group_get_all.assert_called_once_with( 

2132 self.context, share_server['id'] 

2133 ) 

2134 mock_share_server_update.assert_called_once_with( 

2135 self.context, share_server['id'], update_data 

2136 ) 

2137 

2138 mock_rpc.assert_called_once_with( 

2139 self.context, share_server, force=True) 

2140 

2141 def test_unmanage_share_server_in_use(self): 

2142 fake_share = db_utils.create_share() 

2143 fake_share_server = db_utils.create_share_server() 

2144 

2145 fake_share_instance = db_utils.create_share_instance( 

2146 share_id=fake_share['id']) 

2147 share_instance_get_all_mock = self.mock_object( 

2148 db_api, 'share_instance_get_all_by_share_server', 

2149 mock.Mock(return_value=fake_share_instance) 

2150 ) 

2151 

2152 self.assertRaises(exception.ShareServerInUse, 

2153 self.api.unmanage_share_server, 

2154 self.context, 

2155 fake_share_server, True) 

2156 share_instance_get_all_mock.assert_called_once_with( 

2157 self.context, fake_share_server['id'] 

2158 ) 

2159 

2160 def test_unmanage_share_server_in_use_share_groups(self): 

2161 fake_share_server = db_utils.create_share_server() 

2162 fake_share_groups = db_utils.create_share_group() 

2163 

2164 share_instance_get_all_mock = self.mock_object( 

2165 db_api, 'share_instance_get_all_by_share_server', 

2166 mock.Mock(return_value={}) 

2167 ) 

2168 group_get_all_mock = self.mock_object( 

2169 db_api, 'share_group_get_all_by_share_server', 

2170 mock.Mock(return_value=fake_share_groups) 

2171 ) 

2172 

2173 self.assertRaises(exception.ShareServerInUse, 

2174 self.api.unmanage_share_server, 

2175 self.context, 

2176 fake_share_server, True) 

2177 share_instance_get_all_mock.assert_called_once_with( 

2178 self.context, fake_share_server['id'] 

2179 ) 

2180 group_get_all_mock.assert_called_once_with( 

2181 self.context, fake_share_server['id'] 

2182 ) 

2183 

2184 @ddt.data(True, False) 

2185 def test_revert_to_snapshot(self, has_replicas): 

2186 

2187 share = fakes.fake_share(id=uuidutils.generate_uuid(), 

2188 has_replicas=has_replicas) 

2189 self.mock_object(db_api, 'share_get', mock.Mock(return_value=share)) 

2190 mock_handle_revert_to_snapshot_quotas = self.mock_object( 

2191 self.api, '_handle_revert_to_snapshot_quotas', 

2192 mock.Mock(return_value='fake_reservations')) 

2193 mock_revert_to_replicated_snapshot = self.mock_object( 

2194 self.api, '_revert_to_replicated_snapshot') 

2195 mock_revert_to_snapshot = self.mock_object( 

2196 self.api, '_revert_to_snapshot') 

2197 snapshot = fakes.fake_snapshot(share_id=share['id']) 

2198 

2199 self.api.revert_to_snapshot(self.context, share, snapshot) 

2200 

2201 mock_handle_revert_to_snapshot_quotas.assert_called_once_with( 

2202 self.context, share, snapshot) 

2203 if not has_replicas: 

2204 self.assertFalse(mock_revert_to_replicated_snapshot.called) 

2205 mock_revert_to_snapshot.assert_called_once_with( 

2206 self.context, share, snapshot, 'fake_reservations') 

2207 else: 

2208 mock_revert_to_replicated_snapshot.assert_called_once_with( 

2209 self.context, share, snapshot, 'fake_reservations') 

2210 self.assertFalse(mock_revert_to_snapshot.called) 

2211 

2212 @ddt.data(None, 'fake_reservations') 

2213 def test_revert_to_snapshot_exception(self, reservations): 

2214 

2215 share = fakes.fake_share(id=uuidutils.generate_uuid(), 

2216 has_replicas=False) 

2217 self.mock_object(db_api, 'share_get', mock.Mock(return_value=share)) 

2218 self.mock_object( 

2219 self.api, '_handle_revert_to_snapshot_quotas', 

2220 mock.Mock(return_value=reservations)) 

2221 side_effect = exception.ReplicationException(reason='error') 

2222 self.mock_object( 

2223 self.api, '_revert_to_snapshot', 

2224 mock.Mock(side_effect=side_effect)) 

2225 mock_quotas_rollback = self.mock_object(quota.QUOTAS, 'rollback') 

2226 snapshot = fakes.fake_snapshot(share_id=share['id']) 

2227 

2228 self.assertRaises(exception.ReplicationException, 

2229 self.api.revert_to_snapshot, 

2230 self.context, 

2231 share, 

2232 snapshot) 

2233 

2234 if reservations is not None: 

2235 mock_quotas_rollback.assert_called_once_with( 

2236 self.context, reservations, 

2237 share_type_id=share['instance']['share_type_id']) 

2238 else: 

2239 self.assertFalse(mock_quotas_rollback.called) 

2240 

2241 def test_handle_revert_to_snapshot_quotas(self): 

2242 

2243 share = fakes.fake_share( 

2244 id=uuidutils.generate_uuid(), size=1, project_id='fake_project', 

2245 user_id='fake_user', has_replicas=False) 

2246 snapshot = fakes.fake_snapshot( 

2247 id=uuidutils.generate_uuid(), share_id=share['id'], size=1) 

2248 mock_quotas_reserve = self.mock_object(quota.QUOTAS, 'reserve') 

2249 

2250 result = self.api._handle_revert_to_snapshot_quotas( 

2251 self.context, share, snapshot) 

2252 

2253 self.assertIsNone(result) 

2254 self.assertFalse(mock_quotas_reserve.called) 

2255 

2256 def test_handle_revert_to_snapshot_quotas_different_size(self): 

2257 

2258 share = fakes.fake_share( 

2259 id=uuidutils.generate_uuid(), size=1, project_id='fake_project', 

2260 user_id='fake_user', has_replicas=False) 

2261 snapshot = fakes.fake_snapshot( 

2262 id=uuidutils.generate_uuid(), share_id=share['id'], size=2) 

2263 mock_quotas_reserve = self.mock_object( 

2264 quota.QUOTAS, 'reserve', 

2265 mock.Mock(return_value='fake_reservations')) 

2266 

2267 result = self.api._handle_revert_to_snapshot_quotas( 

2268 self.context, share, snapshot) 

2269 

2270 self.assertEqual('fake_reservations', result) 

2271 mock_quotas_reserve.assert_called_once_with( 

2272 self.context, project_id='fake_project', gigabytes=1, 

2273 share_type_id=share['instance']['share_type_id'], 

2274 user_id='fake_user') 

2275 

2276 def test_handle_revert_to_snapshot_quotas_quota_exceeded(self): 

2277 

2278 share = fakes.fake_share( 

2279 id=uuidutils.generate_uuid(), size=1, project_id='fake_project', 

2280 user_id='fake_user', has_replicas=False) 

2281 snapshot = fakes.fake_snapshot( 

2282 id=uuidutils.generate_uuid(), share_id=share['id'], size=2) 

2283 usages = {'gigabytes': {'reserved': 10, 'in_use': 0}} 

2284 quotas = {'gigabytes': 10} 

2285 side_effect = exception.OverQuota( 

2286 overs='fake', usages=usages, quotas=quotas) 

2287 self.mock_object( 

2288 quota.QUOTAS, 'reserve', mock.Mock(side_effect=side_effect)) 

2289 

2290 self.assertRaises(exception.ShareSizeExceedsAvailableQuota, 

2291 self.api._handle_revert_to_snapshot_quotas, 

2292 self.context, 

2293 share, 

2294 snapshot) 

2295 

2296 def test__revert_to_snapshot(self): 

2297 

2298 share = fakes.fake_share( 

2299 id=uuidutils.generate_uuid(), size=1, project_id='fake_project', 

2300 user_id='fake_user', has_replicas=False) 

2301 snapshot = fakes.fake_snapshot( 

2302 id=uuidutils.generate_uuid(), share_id=share['id'], size=2) 

2303 mock_share_update = self.mock_object(db_api, 'share_update') 

2304 mock_share_snapshot_update = self.mock_object( 

2305 db_api, 'share_snapshot_update') 

2306 mock_revert_rpc_call = self.mock_object( 

2307 self.share_rpcapi, 'revert_to_snapshot') 

2308 

2309 self.api._revert_to_snapshot( 

2310 self.context, share, snapshot, 'fake_reservations') 

2311 

2312 mock_share_update.assert_called_once_with( 

2313 self.context, share['id'], {'status': constants.STATUS_REVERTING}) 

2314 mock_share_snapshot_update.assert_called_once_with( 

2315 self.context, snapshot['id'], 

2316 {'status': constants.STATUS_RESTORING}) 

2317 mock_revert_rpc_call.assert_called_once_with( 

2318 self.context, share, snapshot, share['instance']['host'], 

2319 'fake_reservations') 

2320 

2321 def test_revert_to_replicated_snapshot(self): 

2322 

2323 share = fakes.fake_share( 

2324 has_replicas=True, status=constants.STATUS_AVAILABLE) 

2325 snapshot = fakes.fake_snapshot(share_instance_id='id1') 

2326 snapshot_instance = fakes.fake_snapshot_instance( 

2327 base_snapshot=snapshot, id='sid1') 

2328 replicas = [ 

2329 fakes.fake_replica( 

2330 id='rid1', replica_state=constants.REPLICA_STATE_ACTIVE), 

2331 fakes.fake_replica( 

2332 id='rid2', replica_state=constants.REPLICA_STATE_IN_SYNC), 

2333 ] 

2334 self.mock_object( 

2335 db_api, 'share_replicas_get_available_active_replica', 

2336 mock.Mock(return_value=replicas[0])) 

2337 self.mock_object( 

2338 db_api, 'share_snapshot_instance_get_all_with_filters', 

2339 mock.Mock(return_value=[snapshot_instance])) 

2340 mock_share_replica_update = self.mock_object( 

2341 db_api, 'share_replica_update') 

2342 mock_share_snapshot_instance_update = self.mock_object( 

2343 db_api, 'share_snapshot_instance_update') 

2344 mock_revert_rpc_call = self.mock_object( 

2345 self.share_rpcapi, 'revert_to_snapshot') 

2346 

2347 self.api._revert_to_replicated_snapshot( 

2348 self.context, share, snapshot, 'fake_reservations') 

2349 

2350 mock_share_replica_update.assert_called_once_with( 

2351 self.context, 'rid1', {'status': constants.STATUS_REVERTING}) 

2352 mock_share_snapshot_instance_update.assert_called_once_with( 

2353 self.context, 'sid1', {'status': constants.STATUS_RESTORING}) 

2354 mock_revert_rpc_call.assert_called_once_with( 

2355 self.context, share, snapshot, replicas[0]['host'], 

2356 'fake_reservations') 

2357 

2358 def test_revert_to_replicated_snapshot_no_active_replica(self): 

2359 

2360 share = fakes.fake_share( 

2361 has_replicas=True, status=constants.STATUS_AVAILABLE) 

2362 snapshot = fakes.fake_snapshot(share_instance_id='id1') 

2363 self.mock_object( 

2364 db_api, 'share_replicas_get_available_active_replica', 

2365 mock.Mock(return_value=None)) 

2366 

2367 self.assertRaises(exception.ReplicationException, 

2368 self.api._revert_to_replicated_snapshot, 

2369 self.context, 

2370 share, 

2371 snapshot, 

2372 'fake_reservations') 

2373 

2374 def test_revert_to_replicated_snapshot_no_snapshot_instance(self): 

2375 

2376 share = fakes.fake_share( 

2377 has_replicas=True, status=constants.STATUS_AVAILABLE) 

2378 snapshot = fakes.fake_snapshot(share_instance_id='id1') 

2379 replicas = [ 

2380 fakes.fake_replica( 

2381 id='rid1', replica_state=constants.REPLICA_STATE_ACTIVE), 

2382 fakes.fake_replica( 

2383 id='rid2', replica_state=constants.REPLICA_STATE_IN_SYNC), 

2384 ] 

2385 self.mock_object( 

2386 db_api, 'share_replicas_get_available_active_replica', 

2387 mock.Mock(return_value=replicas[0])) 

2388 self.mock_object( 

2389 db_api, 'share_snapshot_instance_get_all_with_filters', 

2390 mock.Mock(return_value=[None])) 

2391 

2392 self.assertRaises(exception.ReplicationException, 

2393 self.api._revert_to_replicated_snapshot, 

2394 self.context, 

2395 share, 

2396 snapshot, 

2397 'fake_reservations') 

2398 

2399 def test_create_snapshot_for_replicated_share(self): 

2400 share = fakes.fake_share( 

2401 has_replicas=True, status=constants.STATUS_AVAILABLE) 

2402 snapshot = fakes.fake_snapshot( 

2403 create_instance=True, share_instance_id='id2') 

2404 replicas = [ 

2405 fakes.fake_replica( 

2406 id='id1', replica_state=constants.REPLICA_STATE_ACTIVE), 

2407 fakes.fake_replica( 

2408 id='id2', replica_state=constants.REPLICA_STATE_IN_SYNC) 

2409 ] 

2410 self.mock_object(share_api.policy, 'check_policy') 

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

2412 mock.Mock(return_value='reservation')) 

2413 self.mock_object( 

2414 db_api, 'share_snapshot_create', mock.Mock(return_value=snapshot)) 

2415 self.mock_object(db_api, 'share_replicas_get_all_by_share', 

2416 mock.Mock(return_value=replicas)) 

2417 self.mock_object( 

2418 db_api, 'share_snapshot_get', mock.Mock(return_value=snapshot)) 

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

2420 mock_instance_create_call = self.mock_object( 

2421 db_api, 'share_snapshot_instance_create') 

2422 mock_snapshot_rpc_call = self.mock_object( 

2423 self.share_rpcapi, 'create_snapshot') 

2424 mock_replicated_snapshot_rpc_call = self.mock_object( 

2425 self.share_rpcapi, 'create_replicated_snapshot') 

2426 snapshot_instance_args = { 

2427 'status': constants.STATUS_CREATING, 

2428 'progress': '0%', 

2429 'share_instance_id': 'id1', 

2430 } 

2431 

2432 retval = self.api.create_snapshot( 

2433 self.context, share, 'fake_name', 'fake_description') 

2434 

2435 self.assertEqual(snapshot['id'], retval['id']) 

2436 mock_instance_create_call.assert_called_once_with( 

2437 self.context, snapshot['id'], snapshot_instance_args) 

2438 self.assertFalse(mock_snapshot_rpc_call.called) 

2439 self.assertTrue(mock_replicated_snapshot_rpc_call.called) 

2440 

2441 @mock.patch.object(db_api, 'share_instance_get_all_by_share_server', 

2442 mock.Mock(return_value=[])) 

2443 @mock.patch.object(db_api, 'share_group_get_all_by_share_server', 

2444 mock.Mock(return_value=[])) 

2445 def test_delete_share_server_no_dependent_shares(self): 

2446 server = {'id': 'fake_share_server_id'} 

2447 server_returned = { 

2448 'id': 'fake_share_server_id', 

2449 } 

2450 self.mock_object(db_api, 'share_server_update', 

2451 mock.Mock(return_value=server_returned)) 

2452 self.api.delete_share_server(self.context, server) 

2453 db_api.share_instance_get_all_by_share_server.assert_called_once_with( 

2454 self.context, server['id']) 

2455 (db_api.share_group_get_all_by_share_server. 

2456 assert_called_once_with(self.context, server['id'])) 

2457 self.share_rpcapi.delete_share_server.assert_called_once_with( 

2458 self.context, server_returned) 

2459 

2460 @mock.patch.object(db_api, 'share_instance_get_all_by_share_server', 

2461 mock.Mock(return_value=['fake_share', ])) 

2462 @mock.patch.object(db_api, 'share_group_get_all_by_share_server', 

2463 mock.Mock(return_value=[])) 

2464 def test_delete_share_server_dependent_share_exists(self): 

2465 server = {'id': 'fake_share_server_id'} 

2466 self.assertRaises(exception.ShareServerInUse, 

2467 self.api.delete_share_server, 

2468 self.context, 

2469 server) 

2470 db_api.share_instance_get_all_by_share_server.assert_called_once_with( 

2471 self.context, server['id']) 

2472 

2473 @mock.patch.object(db_api, 'share_instance_get_all_by_share_server', 

2474 mock.Mock(return_value=[])) 

2475 @mock.patch.object(db_api, 'share_group_get_all_by_share_server', 

2476 mock.Mock(return_value=['fake_group', ])) 

2477 def test_delete_share_server_dependent_group_exists(self): 

2478 server = {'id': 'fake_share_server_id'} 

2479 self.assertRaises(exception.ShareServerInUse, 

2480 self.api.delete_share_server, 

2481 self.context, 

2482 server) 

2483 

2484 db_api.share_instance_get_all_by_share_server.assert_called_once_with( 

2485 self.context, server['id']) 

2486 (db_api.share_group_get_all_by_share_server. 

2487 assert_called_once_with(self.context, server['id'])) 

2488 

2489 @mock.patch.object(db_api, 'share_snapshot_instance_update', mock.Mock()) 

2490 def test_delete_snapshot(self): 

2491 snapshot = db_utils.create_snapshot( 

2492 with_share=True, status=constants.STATUS_AVAILABLE) 

2493 share = snapshot['share'] 

2494 

2495 with mock.patch.object(db_api, 'share_get', 

2496 mock.Mock(return_value=share)): 

2497 self.api.delete_snapshot(self.context, snapshot) 

2498 self.share_rpcapi.delete_snapshot.assert_called_once_with( 

2499 self.context, snapshot, share['host'], force=False, 

2500 deferred_delete=False) 

2501 share_api.policy.check_policy.assert_called_once_with( 

2502 self.context, 'share', 'delete_snapshot', snapshot) 

2503 db_api.share_snapshot_instance_update.assert_called_once_with( 

2504 self.context, 

2505 snapshot['instance']['id'], 

2506 {'status': constants.STATUS_DELETING}) 

2507 db_api.share_get.assert_called_once_with( 

2508 self.context, snapshot['share_id']) 

2509 

2510 @ddt.data(True, False) 

2511 def test_delete_snapshot_deferred(self, force): 

2512 CONF.set_default("is_deferred_deletion_enabled", True) 

2513 snapshot = db_utils.create_snapshot( 

2514 with_share=True, status=constants.STATUS_AVAILABLE) 

2515 share = snapshot['share'] 

2516 

2517 self.mock_object(db_api, 'share_snapshot_instance_update', 

2518 mock.Mock()) 

2519 

2520 with mock.patch.object(db_api, 'share_get', 

2521 mock.Mock(return_value=share)): 

2522 self.api.delete_snapshot(self.context, snapshot, force=force) 

2523 if force: 

2524 self.share_rpcapi.delete_snapshot.assert_called_once_with( 

2525 self.context, snapshot, share['host'], force=True, 

2526 deferred_delete=False) 

2527 db_api.share_snapshot_instance_update.assert_called_once_with( 

2528 self.context, 

2529 snapshot['instance']['id'], 

2530 {'status': constants.STATUS_DELETING}) 

2531 else: 

2532 self.share_rpcapi.delete_snapshot.assert_called_once_with( 

2533 self.context, snapshot, share['host'], force=False, 

2534 deferred_delete=True) 

2535 db_api.share_snapshot_instance_update.assert_called_once_with( 

2536 self.context, 

2537 snapshot['instance']['id'], 

2538 {'status': constants.STATUS_DEFERRED_DELETING}) 

2539 

2540 share_api.policy.check_policy.assert_called_once_with( 

2541 self.context, 'share', 'delete_snapshot', snapshot) 

2542 db_api.share_get.assert_called_once_with( 

2543 self.context, snapshot['share_id']) 

2544 

2545 def test_delete_snapshot_wrong_status(self): 

2546 snapshot = db_utils.create_snapshot( 

2547 with_share=True, status=constants.STATUS_CREATING) 

2548 

2549 self.assertRaises(exception.InvalidShareSnapshot, 

2550 self.api.delete_snapshot, 

2551 self.context, 

2552 snapshot) 

2553 share_api.policy.check_policy.assert_called_once_with( 

2554 self.context, 'share', 'delete_snapshot', snapshot) 

2555 

2556 @ddt.data(constants.STATUS_MANAGING, constants.STATUS_ERROR_DELETING, 

2557 constants.STATUS_CREATING, constants.STATUS_AVAILABLE) 

2558 def test_delete_snapshot_force_delete(self, status): 

2559 share = fakes.fake_share(id=uuidutils.generate_uuid(), 

2560 has_replicas=False) 

2561 snapshot = fakes.fake_snapshot(aggregate_status=status, share=share) 

2562 snapshot_instance = fakes.fake_snapshot_instance( 

2563 base_snapshot=snapshot) 

2564 self.mock_object(db_api, 'share_get', mock.Mock(return_value=share)) 

2565 self.mock_object( 

2566 db_api, 'share_snapshot_instance_get_all_with_filters', 

2567 mock.Mock(return_value=[snapshot_instance])) 

2568 mock_instance_update_call = self.mock_object( 

2569 db_api, 'share_snapshot_instance_update') 

2570 mock_rpc_call = self.mock_object(self.share_rpcapi, 'delete_snapshot') 

2571 

2572 retval = self.api.delete_snapshot(self.context, snapshot, force=True) 

2573 

2574 self.assertIsNone(retval) 

2575 mock_instance_update_call.assert_called_once_with( 

2576 self.context, snapshot_instance['id'], 

2577 {'status': constants.STATUS_DELETING}) 

2578 mock_rpc_call.assert_called_once_with( 

2579 self.context, snapshot, share['instance']['host'], force=True, 

2580 deferred_delete=False) 

2581 

2582 @ddt.data(True, False) 

2583 def test_delete_snapshot_replicated_snapshot(self, force): 

2584 share = fakes.fake_share(has_replicas=True) 

2585 snapshot = fakes.fake_snapshot( 

2586 create_instance=True, share_id=share['id'], 

2587 status=constants.STATUS_ERROR) 

2588 snapshot_instance = fakes.fake_snapshot_instance( 

2589 base_snapshot=snapshot) 

2590 expected_update_calls = [ 

2591 mock.call(self.context, x, {'status': constants.STATUS_DELETING}) 

2592 for x in (snapshot['instance']['id'], snapshot_instance['id']) 

2593 ] 

2594 self.mock_object(db_api, 'share_get', mock.Mock(return_value=share)) 

2595 self.mock_object( 

2596 db_api, 'share_snapshot_instance_get_all_with_filters', 

2597 mock.Mock(return_value=[snapshot['instance'], snapshot_instance])) 

2598 mock_db_update_call = self.mock_object( 

2599 db_api, 'share_snapshot_instance_update') 

2600 mock_snapshot_rpc_call = self.mock_object( 

2601 self.share_rpcapi, 'delete_snapshot') 

2602 mock_replicated_snapshot_rpc_call = self.mock_object( 

2603 self.share_rpcapi, 'delete_replicated_snapshot') 

2604 

2605 retval = self.api.delete_snapshot(self.context, snapshot, force=force) 

2606 

2607 self.assertIsNone(retval) 

2608 self.assertEqual(2, mock_db_update_call.call_count) 

2609 mock_db_update_call.assert_has_calls(expected_update_calls) 

2610 mock_replicated_snapshot_rpc_call.assert_called_once_with( 

2611 self.context, snapshot, share['instance']['host'], 

2612 share_id=share['id'], force=force) 

2613 self.assertFalse(mock_snapshot_rpc_call.called) 

2614 

2615 def test_create_snapshot_if_share_not_available(self): 

2616 share = db_utils.create_share(status=constants.STATUS_ERROR) 

2617 self.assertRaises(exception.InvalidShare, 

2618 self.api.create_snapshot, 

2619 self.context, 

2620 share, 

2621 'fakename', 

2622 'fakedesc') 

2623 share_api.policy.check_policy.assert_called_once_with( 

2624 self.context, 'share', 'create_snapshot', share) 

2625 

2626 def test_create_snapshot_invalid_task_state(self): 

2627 share = db_utils.create_share( 

2628 status=constants.STATUS_AVAILABLE, 

2629 task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS) 

2630 self.assertRaises(exception.ShareBusyException, 

2631 self.api.create_snapshot, 

2632 self.context, 

2633 share, 

2634 'fakename', 

2635 'fakedesc') 

2636 share_api.policy.check_policy.assert_called_once_with( 

2637 self.context, 'share', 'create_snapshot', share) 

2638 

2639 def test_create_snapshot_fail(self): 

2640 share = fakes.fake_share( 

2641 has_replicas=False, status=constants.STATUS_AVAILABLE) 

2642 mock_db_share_snapshot_create = self.mock_object( 

2643 db_api, 'share_snapshot_create', mock.Mock( 

2644 side_effect=exception.NotFound)) 

2645 

2646 self.mock_object(quota.QUOTAS, 'rollback') 

2647 

2648 self.assertRaises(exception.NotFound, 

2649 self.api.create_snapshot, 

2650 self.context, share, 

2651 'fake_name', 'fake_desc') 

2652 

2653 self.assertTrue(mock_db_share_snapshot_create.called) 

2654 quota.QUOTAS.rollback.assert_called_once_with( 

2655 self.context, 

2656 mock.ANY, 

2657 share_type_id=share['instance']['share_type_id']) 

2658 

2659 def test_create_snapshot_quota_commit_fail(self): 

2660 share = fakes.fake_share( 

2661 has_replicas=False, status=constants.STATUS_AVAILABLE) 

2662 snapshot = fakes.fake_snapshot( 

2663 create_instance=True, share_instance_id='id2') 

2664 self.mock_object( 

2665 quota.QUOTAS, 'commit', mock.Mock( 

2666 side_effect=exception.QuotaError('fake'))) 

2667 

2668 self.mock_object(db_api, 'share_snapshot_create', mock.Mock( 

2669 return_value=snapshot)) 

2670 self.mock_object(db_api, 'share_snapshot_instance_delete') 

2671 self.mock_object(quota.QUOTAS, 'rollback') 

2672 

2673 self.assertRaises(exception.QuotaError, 

2674 self.api.create_snapshot, 

2675 self.context, share, 

2676 'fake_name', 'fake_desc') 

2677 

2678 quota.QUOTAS.rollback.assert_called_once_with( 

2679 self.context, 

2680 mock.ANY, 

2681 share_type_id=share['instance']['share_type_id']) 

2682 

2683 @ddt.data({'use_scheduler': False, 'valid_host': 'fake', 

2684 'az': None}, 

2685 {'use_scheduler': True, 'valid_host': None, 

2686 'az': None}, 

2687 {'use_scheduler': True, 'valid_host': None, 

2688 'az': "fakeaz2"}) 

2689 @ddt.unpack 

2690 def test_create_from_snapshot(self, use_scheduler, valid_host, az): 

2691 snapshot, share, share_data, request_spec = ( 

2692 self._setup_create_from_snapshot_mocks( 

2693 use_scheduler=use_scheduler, host=valid_host) 

2694 ) 

2695 share_type = fakes.fake_share_type() 

2696 

2697 self.mock_object(db_api, 'share_snapshot_get', 

2698 mock.Mock(return_value=snapshot)) 

2699 mock_get_share_type_call = self.mock_object( 

2700 share_types, 'get_share_type', mock.Mock(return_value=share_type)) 

2701 

2702 self.api.create( 

2703 self.context, 

2704 share_data['share_proto'], 

2705 None, # NOTE(u_glide): Get share size from snapshot 

2706 share_data['display_name'], 

2707 share_data['display_description'], 

2708 snapshot_id=snapshot['id'], 

2709 availability_zone=az, 

2710 ) 

2711 

2712 expected_az = snapshot['share']['availability_zone'] if not az else az 

2713 share_data.pop('availability_zone') 

2714 

2715 mock_get_share_type_call.assert_called_once_with( 

2716 self.context, share['share_type_id']) 

2717 self.assertSubDictMatch(share_data, 

2718 db_api.share_create.call_args[0][1]) 

2719 self.api.create_instance.assert_called_once_with( 

2720 self.context, share, share_network_id=share['share_network_id'], 

2721 host=valid_host, share_type_id=share_type['id'], 

2722 availability_zone=expected_az, 

2723 share_group=None, share_group_snapshot_member=None, 

2724 availability_zones=None, 

2725 az_request_multiple_subnet_support_map=None, 

2726 snapshot_host=snapshot['share']['instance']['host'], 

2727 scheduler_hints=None, mount_point_name=None, 

2728 encryption_key_ref=None) 

2729 share_api.policy.check_policy.assert_called_once_with( 

2730 self.context, 'share_snapshot', 'get_snapshot', 

2731 snapshot, do_raise=False) 

2732 quota.QUOTAS.reserve.assert_called_once_with( 

2733 self.context, share_type_id=share_type['id'], 

2734 gigabytes=1, shares=1) 

2735 quota.QUOTAS.commit.assert_called_once_with( 

2736 self.context, 'reservation', share_type_id=share_type['id']) 

2737 

2738 def test_create_share_with_share_group(self): 

2739 extra_specs = {'replication_type': constants.REPLICATION_TYPE_READABLE} 

2740 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

2741 share_type = db_api.share_type_get(self.context, share_type['id']) 

2742 group = db_utils.create_share_group( 

2743 status=constants.STATUS_AVAILABLE, 

2744 share_types=[share_type['id']]) 

2745 share, share_data = self._setup_create_mocks( 

2746 share_type_id=share_type['id'], 

2747 share_group_id=group['id']) 

2748 

2749 share_instance = db_utils.create_share_instance( 

2750 share_id=share['id']) 

2751 sg_snap_member = { 

2752 'id': 'fake_sg_snap_member_id', 

2753 'share_instance': share_instance 

2754 } 

2755 

2756 az = share_data.pop('availability_zone') 

2757 

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

2759 mock.Mock(return_value='reservation')) 

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

2761 

2762 self.api.create( 

2763 self.context, 

2764 share_data['share_proto'], 

2765 share_data['size'], 

2766 share_data['display_name'], 

2767 share_data['display_description'], 

2768 availability_zone=az, 

2769 share_type=share_type, 

2770 share_group_id=group['id'], 

2771 share_group_snapshot_member=sg_snap_member, 

2772 ) 

2773 quota.QUOTAS.reserve.assert_called_once_with( 

2774 self.context, share_type_id=share_type['id'], 

2775 gigabytes=1, shares=1, share_replicas=1, replica_gigabytes=1) 

2776 quota.QUOTAS.commit.assert_called_once_with( 

2777 self.context, 'reservation', share_type_id=share_type['id'] 

2778 ) 

2779 

2780 def test_create_share_share_type_contains_replication_type(self): 

2781 extra_specs = {'replication_type': constants.REPLICATION_TYPE_READABLE} 

2782 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

2783 share_type = db_api.share_type_get(self.context, share_type['id']) 

2784 share, share_data = self._setup_create_mocks( 

2785 share_type_id=share_type['id']) 

2786 az = share_data.pop('availability_zone') 

2787 

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

2789 mock.Mock(return_value='reservation')) 

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

2791 

2792 self.api.create( 

2793 self.context, 

2794 share_data['share_proto'], 

2795 share_data['size'], 

2796 share_data['display_name'], 

2797 share_data['display_description'], 

2798 availability_zone=az, 

2799 share_type=share_type 

2800 ) 

2801 quota.QUOTAS.reserve.assert_called_once_with( 

2802 self.context, share_type_id=share_type['id'], 

2803 gigabytes=1, shares=1, share_replicas=1, replica_gigabytes=1) 

2804 quota.QUOTAS.commit.assert_called_once_with( 

2805 self.context, 'reservation', share_type_id=share_type['id'] 

2806 ) 

2807 

2808 def test_create_from_snapshot_az_different_from_source(self): 

2809 snapshot, share, share_data, request_spec = ( 

2810 self._setup_create_from_snapshot_mocks(use_scheduler=False) 

2811 ) 

2812 

2813 self.assertRaises(exception.InvalidInput, self.api.create, 

2814 self.context, share_data['share_proto'], 

2815 share_data['size'], 

2816 share_data['display_name'], 

2817 share_data['display_description'], 

2818 snapshot_id=snapshot['id'], 

2819 availability_zone='fake_different_az') 

2820 

2821 def test_create_from_snapshot_with_different_share_type(self): 

2822 snapshot, share, share_data, request_spec = ( 

2823 self._setup_create_from_snapshot_mocks() 

2824 ) 

2825 

2826 share_type = {'id': 'super_fake_share_type'} 

2827 

2828 self.assertRaises(exception.InvalidInput, self.api.create, 

2829 self.context, share_data['share_proto'], 

2830 share_data['size'], 

2831 share_data['display_name'], 

2832 share_data['display_description'], 

2833 snapshot_id=snapshot['id'], 

2834 availability_zone=share_data['availability_zone'], 

2835 share_type=share_type) 

2836 

2837 def test_get_snapshot(self): 

2838 fake_get_snap = {'fake_key': 'fake_val'} 

2839 with mock.patch.object(db_api, 'share_snapshot_get', 

2840 mock.Mock(return_value=fake_get_snap)): 

2841 rule = self.api.get_snapshot(self.context, 'fakeid') 

2842 self.assertEqual(fake_get_snap, rule) 

2843 share_api.policy.check_policy.assert_called_once_with( 

2844 self.context, 'share_snapshot', 'get_snapshot', rule, 

2845 do_raise=False) 

2846 db_api.share_snapshot_get.assert_called_once_with( 

2847 self.context, 'fakeid') 

2848 

2849 def test_get_snapshot_non_admin_deferred_state(self): 

2850 fake_get_snap = { 

2851 'fake_key': 'fake_val', 'status': 'deferred_deleting' 

2852 } 

2853 with mock.patch.object(db_api, 'share_snapshot_get', 

2854 mock.Mock(return_value=fake_get_snap)): 

2855 self.mock_object( 

2856 policy, 'check_policy', mock.Mock(side_effect=[True, False])) 

2857 self.assertRaises(exception.NotFound, self.api.get_snapshot, 

2858 self.context, 'fakeid') 

2859 

2860 def test_get_snapshot_not_authorized(self): 

2861 fake_get_snap = {'fake_key': 'fake_val'} 

2862 share_api.policy.check_policy.return_value = False 

2863 with mock.patch.object(db_api, 'share_snapshot_get', 

2864 mock.Mock(return_value=fake_get_snap)): 

2865 self.assertRaises(exception.NotFound, 

2866 self.api.get_snapshot, 

2867 self.context, 'fakeid') 

2868 share_api.policy.check_policy.assert_called_once_with( 

2869 self.context, 'share_snapshot', 'get_snapshot', 

2870 fake_get_snap, do_raise=False) 

2871 db_api.share_snapshot_get.assert_called_once_with( 

2872 self.context, 'fakeid') 

2873 

2874 def test_create_from_snapshot_not_available(self): 

2875 snapshot = db_utils.create_snapshot( 

2876 with_share=True, status=constants.STATUS_ERROR) 

2877 self.assertRaises(exception.InvalidShareSnapshot, self.api.create, 

2878 self.context, 'nfs', '1', 'fakename', 

2879 'fakedesc', snapshot_id=snapshot['id'], 

2880 availability_zone='fakeaz') 

2881 

2882 def test_create_from_snapshot_larger_size(self): 

2883 snapshot = db_utils.create_snapshot( 

2884 size=100, status=constants.STATUS_AVAILABLE, with_share=True) 

2885 self.assertRaises(exception.InvalidInput, self.api.create, 

2886 self.context, 'nfs', 1, 'fakename', 'fakedesc', 

2887 availability_zone='fakeaz', 

2888 snapshot_id=snapshot['id']) 

2889 

2890 def test_create_share_wrong_size_0(self): 

2891 self.assertRaises(exception.InvalidInput, self.api.create, 

2892 self.context, 'nfs', 0, 'fakename', 'fakedesc', 

2893 availability_zone='fakeaz') 

2894 

2895 def test_create_share_wrong_size_some(self): 

2896 self.assertRaises(exception.InvalidInput, self.api.create, 

2897 self.context, 'nfs', 'some', 'fakename', 

2898 'fakedesc', availability_zone='fakeaz') 

2899 

2900 @ddt.data(constants.STATUS_AVAILABLE, constants.STATUS_ERROR) 

2901 def test_delete(self, status): 

2902 share = self._setup_delete_mocks(status) 

2903 

2904 self.api.delete(self.context, share) 

2905 

2906 self.api.delete_instance.assert_called_once_with( 

2907 utils.IsAMatcher(context.RequestContext), 

2908 utils.IsAMatcher(models.ShareInstance), force=False 

2909 ) 

2910 db_api.share_snapshot_get_all_for_share.assert_called_once_with( 

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

2912 

2913 def test_delete_quota_with_different_user(self): 

2914 share = self._setup_delete_mocks(constants.STATUS_AVAILABLE) 

2915 diff_user_context = context.RequestContext( 

2916 user_id='fake2', 

2917 project_id='fake', 

2918 is_admin=False 

2919 ) 

2920 

2921 self.api.delete(diff_user_context, share) 

2922 

2923 def test_delete_wrong_status(self): 

2924 share = fakes.fake_share(status='wrongstatus') 

2925 self.mock_object(db_api, 'share_get', mock.Mock(return_value=share)) 

2926 self.assertRaises(exception.InvalidShare, self.api.delete, 

2927 self.context, share) 

2928 

2929 def test_delete_share_has_replicas(self): 

2930 share = self._setup_delete_mocks(constants.STATUS_AVAILABLE, 

2931 replication_type='writable') 

2932 db_utils.create_share_replica(share_id=share['id'], 

2933 replica_state='in_sync') 

2934 db_utils.create_share_replica(share_id=share['id'], 

2935 replica_state='out_of_sync') 

2936 

2937 self.assertRaises(exception.Conflict, self.api.delete, 

2938 self.context, share) 

2939 

2940 @mock.patch.object(db_api, 'count_share_group_snapshot_members_in_share', 

2941 mock.Mock(return_value=2)) 

2942 def test_delete_dependent_share_group_snapshot_members(self): 

2943 share_server_id = 'fake-ss-id' 

2944 share = self._setup_delete_mocks(constants.STATUS_AVAILABLE, 

2945 share_server_id) 

2946 

2947 self.assertRaises(exception.InvalidShare, self.api.delete, 

2948 self.context, share) 

2949 

2950 @mock.patch.object(db_api, 'share_instance_delete', mock.Mock()) 

2951 def test_delete_no_host(self): 

2952 share = self._setup_delete_mocks(constants.STATUS_AVAILABLE, host=None) 

2953 

2954 self.api.delete(self.context, share) 

2955 db_api.share_instance_delete.assert_called_once_with( 

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

2957 need_to_update_usages=True) 

2958 

2959 def test_delete_share_with_snapshots(self): 

2960 share = self._setup_delete_mocks(constants.STATUS_AVAILABLE, 

2961 snapshots=['fake']) 

2962 

2963 self.assertRaises( 

2964 exception.InvalidShare, 

2965 self.api.delete, 

2966 self.context, 

2967 share 

2968 ) 

2969 

2970 def test_delete_share_invalid_task_state(self): 

2971 share = db_utils.create_share( 

2972 status=constants.STATUS_AVAILABLE, 

2973 task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS) 

2974 

2975 self.assertRaises(exception.ShareBusyException, 

2976 self.api.delete, 

2977 self.context, share) 

2978 

2979 def test_delete_share_quota_error(self): 

2980 share = self._setup_delete_mocks(constants.STATUS_AVAILABLE) 

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

2982 mock.Mock(side_effect=exception.QuotaError('fake'))) 

2983 

2984 self.api.delete(self.context, share) 

2985 

2986 def test_delete_locked_share(self): 

2987 self.mock_object( 

2988 self.api.db, 

2989 'resource_lock_get_all', 

2990 mock.Mock(return_value=([{'id': 'l1'}, {'id': 'l2'}], None)) 

2991 ) 

2992 share = self._setup_delete_mocks('available') 

2993 

2994 self.assertRaises(exception.InvalidShare, 

2995 self.api.delete, 

2996 self.context, 

2997 share) 

2998 

2999 # lock check decorator executed first, nothing else is invoked 

3000 self.api.delete_instance.assert_not_called() 

3001 db_api.share_snapshot_get_all_for_share.assert_not_called() 

3002 

3003 @ddt.data({'status': constants.STATUS_AVAILABLE, 'force': False}, 

3004 {'status': constants.STATUS_ERROR, 'force': True}) 

3005 @ddt.unpack 

3006 def test_delete_share_instance(self, status, force): 

3007 instance = self._setup_delete_share_instance_mocks( 

3008 status=status, share_server_id='fake') 

3009 

3010 self.api.delete_instance(self.context, instance, force=force) 

3011 

3012 db_api.share_instance_update.assert_called_once_with( 

3013 self.context, 

3014 instance['id'], 

3015 {'status': constants.STATUS_DELETING, 

3016 'terminated_at': self.dt_utc} 

3017 ) 

3018 self.api.share_rpcapi.delete_share_instance.\ 

3019 assert_called_once_with( 

3020 self.context, 

3021 instance, 

3022 force=force, 

3023 deferred_delete=False 

3024 ) 

3025 db_api.share_server_update( 

3026 self.context, 

3027 instance['share_server_id'], 

3028 {'updated_at': self.dt_utc} 

3029 ) 

3030 

3031 @ddt.data({'status': constants.STATUS_DEFERRED_DELETING, 'force': True}, 

3032 {'status': constants.STATUS_AVAILABLE, 'force': False}, 

3033 {'status': constants.STATUS_AVAILABLE, 'force': True}) 

3034 @ddt.unpack 

3035 def test_delete_share_instance_deferred(self, status, force): 

3036 CONF.set_default("is_deferred_deletion_enabled", True) 

3037 instance = self._setup_delete_share_instance_mocks( 

3038 status=status, share_server_id='fake') 

3039 

3040 self.api.delete_instance(self.context, instance, force=force) 

3041 if force: 

3042 if status != constants.STATUS_DEFERRED_DELETING: 

3043 db_api.share_instance_update.assert_called_once_with( 

3044 self.context, 

3045 instance['id'], 

3046 {'status': constants.STATUS_DELETING, 

3047 'terminated_at': self.dt_utc} 

3048 ) 

3049 self.api.share_rpcapi.delete_share_instance.\ 

3050 assert_called_once_with( 

3051 self.context, 

3052 instance, 

3053 force=True, 

3054 deferred_delete=False 

3055 ) 

3056 else: 

3057 db_api.share_instance_update.assert_called_once_with( 

3058 self.context, 

3059 instance['id'], 

3060 {'status': constants.STATUS_DEFERRED_DELETING, 

3061 'terminated_at': self.dt_utc} 

3062 ) 

3063 self.api.share_rpcapi.delete_share_instance.\ 

3064 assert_called_once_with( 

3065 self.context, 

3066 instance, 

3067 force=False, 

3068 deferred_delete=True 

3069 ) 

3070 db_api.share_server_update( 

3071 self.context, 

3072 instance['share_server_id'], 

3073 {'updated_at': self.dt_utc} 

3074 ) 

3075 

3076 def test_delete_share_instance_invalid_status(self): 

3077 instance = self._setup_delete_share_instance_mocks( 

3078 status=constants.STATUS_CREATING, share_server_id='fake') 

3079 

3080 self.assertRaises( 

3081 exception.InvalidShareInstance, 

3082 self.api.delete_instance, 

3083 self.context, 

3084 instance 

3085 ) 

3086 

3087 def test_get(self): 

3088 share = db_utils.create_share() 

3089 with mock.patch.object(db_api, 'share_get', 

3090 mock.Mock(return_value=share)): 

3091 result = self.api.get(self.context, 'fakeid') 

3092 self.assertEqual(share, result) 

3093 share_api.policy.check_policy.assert_called_once_with( 

3094 self.context, 'share', 'get', share, do_raise=False) 

3095 db_api.share_get.assert_called_once_with( 

3096 self.context, 'fakeid') 

3097 

3098 def test_get_admin_deferred_state(self): 

3099 rv = { 

3100 'id': 'fake_id', 

3101 'is_public': False, 

3102 'name': 'bar', 

3103 'status': constants.STATUS_ERROR_DEFERRED_DELETING, 

3104 'project_id': 'fake_pid_2', 

3105 'share_server_id': 'fake_server_3', 

3106 } 

3107 

3108 self.mock_object(db_api, 'share_get', 

3109 mock.Mock(return_value=rv)) 

3110 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

3111 self.mock_object( 

3112 policy, 'check_policy', mock.Mock(side_effect=[True, True])) 

3113 share = self.api.get(ctx, 'fake_id') 

3114 self.assertEqual(rv, share) 

3115 

3116 def test_get_non_admin_deferred_state(self): 

3117 rv = { 

3118 'id': 'fake_id', 

3119 'is_public': False, 

3120 'name': 'bar', 

3121 'status': constants.STATUS_ERROR_DEFERRED_DELETING, 

3122 'project_id': 'fake_pid_2', 

3123 'share_server_id': 'fake_server_3', 

3124 } 

3125 

3126 self.mock_object(db_api, 'share_get', 

3127 mock.Mock(return_value=rv)) 

3128 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

3129 self.mock_object( 

3130 policy, 'check_policy', mock.Mock(side_effect=[True, False])) 

3131 

3132 self.assertRaises( 

3133 exception.NotFound, 

3134 self.api.get, ctx, 'fake_id') 

3135 

3136 def test_get_not_authorized(self): 

3137 share = db_utils.create_share( 

3138 is_public=False, 

3139 project_id='5db325fc4de14fe1a860ff69f190c78c') 

3140 share_api.policy.check_policy.return_value = False 

3141 ctx = context.RequestContext('df6d65cc1f8946ba86be06b8140ec4b3', 

3142 'e8133457b853436591a7e4610e7ce679', 

3143 is_admin=False) 

3144 with mock.patch.object(db_api, 'share_get', 

3145 mock.Mock(return_value=share)): 

3146 

3147 self.assertRaises(exception.NotFound, 

3148 self.api.get, 

3149 ctx, 

3150 share['id']) 

3151 share_api.policy.check_policy.assert_called_once_with( 

3152 ctx, 'share', 'get', share, do_raise=False) 

3153 db_api.share_get.assert_called_once_with(ctx, share['id']) 

3154 

3155 @mock.patch.object(db_api, 'share_snapshot_get_all_by_project', 

3156 mock.Mock()) 

3157 def test_get_all_snapshots_admin_not_all_tenants(self): 

3158 ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=True) 

3159 mock_policy = self.mock_object(share_api.policy, 'check_policy', 

3160 mock.Mock(return_value=False)) 

3161 self.api.get_all_snapshots(ctx) 

3162 mock_policy.assert_has_calls([ 

3163 mock.call(ctx, 'share_snapshot', 'get_all_snapshots'), 

3164 mock.call( 

3165 ctx, 'share_snapshot', 

3166 'list_snapshots_in_deferred_deletion_states', 

3167 do_raise=False)]) 

3168 db_api.share_snapshot_get_all_by_project.assert_called_once_with( 

3169 ctx, 'fakepid', limit=None, offset=None, sort_dir='desc', 

3170 sort_key='share_id', filters={}) 

3171 

3172 @mock.patch.object(db_api, 'share_snapshot_get_all', mock.Mock()) 

3173 def test_get_all_snapshots_admin_all_tenants(self): 

3174 mock_policy = self.mock_object( 

3175 share_api.policy, 'check_policy', 

3176 mock.Mock(side_effect=[False, True, False])) 

3177 self.api.get_all_snapshots(self.context, 

3178 search_opts={'all_tenants': 1}) 

3179 mock_policy.assert_has_calls([ 

3180 mock.call(self.context, 'share_snapshot', 'get_all_snapshots'), 

3181 mock.call( 

3182 self.context, 'share_snapshot', 

3183 'list_all_projects', 

3184 do_raise=False), 

3185 mock.call( 

3186 self.context, 'share_snapshot', 

3187 'list_snapshots_in_deferred_deletion_states', 

3188 do_raise=False)]) 

3189 db_api.share_snapshot_get_all.assert_called_once_with( 

3190 self.context, limit=None, offset=None, sort_dir='desc', 

3191 sort_key='share_id', filters={}) 

3192 

3193 @mock.patch.object(db_api, 'share_snapshot_get_all_by_project', 

3194 mock.Mock()) 

3195 def test_get_all_snapshots_not_admin(self): 

3196 ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=False) 

3197 mock_policy = self.mock_object(share_api.policy, 'check_policy', 

3198 mock.Mock(return_value=False)) 

3199 self.api.get_all_snapshots(ctx) 

3200 mock_policy.assert_has_calls([ 

3201 mock.call(ctx, 'share_snapshot', 'get_all_snapshots'), 

3202 mock.call( 

3203 ctx, 'share_snapshot', 

3204 'list_snapshots_in_deferred_deletion_states', 

3205 do_raise=False)]) 

3206 db_api.share_snapshot_get_all_by_project.assert_called_once_with( 

3207 ctx, 'fakepid', limit=None, offset=None, sort_dir='desc', 

3208 sort_key='share_id', filters={}) 

3209 

3210 def test_get_all_snapshots_not_admin_search_opts(self): 

3211 search_opts = {'size': 'fakesize'} 

3212 fake_objs = [{'name': 'fakename1'}, search_opts] 

3213 ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=False) 

3214 self.mock_object(db_api, 'share_snapshot_get_all_by_project', 

3215 mock.Mock(return_value=fake_objs)) 

3216 mock_policy = self.mock_object(share_api.policy, 'check_policy', 

3217 mock.Mock(return_value=False)) 

3218 

3219 result = self.api.get_all_snapshots(ctx, search_opts) 

3220 

3221 self.assertEqual(fake_objs, result) 

3222 mock_policy.assert_has_calls([ 

3223 mock.call(ctx, 'share_snapshot', 'get_all_snapshots'), 

3224 mock.call( 

3225 ctx, 'share_snapshot', 

3226 'list_snapshots_in_deferred_deletion_states', 

3227 do_raise=False)]) 

3228 db_api.share_snapshot_get_all_by_project.assert_called_once_with( 

3229 ctx, 'fakepid', limit=None, offset=None, sort_dir='desc', 

3230 sort_key='share_id', filters=search_opts) 

3231 

3232 @ddt.data(({'name': 'fo'}, 0, []), ({'description': 'd'}, 0, []), 

3233 ({'name': 'foo', 'description': 'd'}, 0, []), 

3234 ({'name': 'foo'}, 1, [{'name': 'foo', 'description': 'ds'}]), 

3235 ({'description': 'ds'}, 1, [{'name': 'foo', 

3236 'description': 'ds'}]), 

3237 ({'name~': 'foo', 'description~': 'ds'}, 2, 

3238 [{'name': 'foo', 'description': 'ds'}, 

3239 {'name': 'foo1', 'description': 'ds1'}]), 

3240 ({'name': 'foo', 'description~': 'ds'}, 1, 

3241 [{'name': 'foo', 'description': 'ds'}]), 

3242 ({'name~': 'foo', 'description': 'ds'}, 1, 

3243 [{'name': 'foo', 'description': 'ds'}])) 

3244 @ddt.unpack 

3245 def test_get_all_snapshots_filter_by_name_and_description( 

3246 self, search_opts, get_snapshot_number, res_snapshots): 

3247 fake_objs = [{'name': 'fo2', 'description': 'd2'}, 

3248 {'name': 'foo', 'description': 'ds'}, 

3249 {'name': 'foo1', 'description': 'ds1'}] 

3250 ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=False) 

3251 self.mock_object(db_api, 'share_snapshot_get_all_by_project', 

3252 mock.Mock(return_value=res_snapshots)) 

3253 mock_policy = self.mock_object(share_api.policy, 'check_policy') 

3254 

3255 result = self.api.get_all_snapshots(ctx, search_opts) 

3256 

3257 self.assertEqual(get_snapshot_number, len(result)) 

3258 if get_snapshot_number == 2: 

3259 self.assertEqual(fake_objs[1:], result) 

3260 elif get_snapshot_number == 1: 

3261 self.assertEqual(fake_objs[1:2], result) 

3262 

3263 mock_policy.assert_has_calls([ 

3264 mock.call(ctx, 'share_snapshot', 'get_all_snapshots'), 

3265 mock.call( 

3266 ctx, 'share_snapshot', 

3267 'list_snapshots_in_deferred_deletion_states', 

3268 do_raise=False)]) 

3269 db_api.share_snapshot_get_all_by_project.assert_called_once_with( 

3270 ctx, 'fakepid', limit=None, offset=None, sort_dir='desc', 

3271 sort_key='share_id', filters=search_opts) 

3272 

3273 def test_get_all_snapshots_with_sorting_valid(self): 

3274 self.mock_object( 

3275 db_api, 'share_snapshot_get_all_by_project', 

3276 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SNAPSHOTS[0])) 

3277 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

3278 mock_policy = self.mock_object(share_api.policy, 'check_policy', 

3279 mock.Mock(return_value=False)) 

3280 snapshots = self.api.get_all_snapshots( 

3281 ctx, sort_key='status', sort_dir='asc') 

3282 mock_policy.assert_has_calls([ 

3283 mock.call(ctx, 'share_snapshot', 'get_all_snapshots'), 

3284 mock.call( 

3285 ctx, 'share_snapshot', 

3286 'list_snapshots_in_deferred_deletion_states', 

3287 do_raise=False)]) 

3288 

3289 db_api.share_snapshot_get_all_by_project.assert_called_once_with( 

3290 ctx, 'fake_pid_1', limit=None, offset=None, sort_dir='asc', 

3291 sort_key='status', filters={}) 

3292 self.assertEqual(_FAKE_LIST_OF_ALL_SNAPSHOTS[0], snapshots) 

3293 

3294 def test_get_all_snapshots_sort_key_invalid(self): 

3295 self.mock_object( 

3296 db_api, 'share_snapshot_get_all_by_project', 

3297 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SNAPSHOTS[0])) 

3298 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

3299 self.assertRaises( 

3300 exception.InvalidInput, 

3301 self.api.get_all_snapshots, 

3302 ctx, 

3303 sort_key=1, 

3304 ) 

3305 share_api.policy.check_policy.assert_called_once_with( 

3306 ctx, 'share_snapshot', 'get_all_snapshots') 

3307 

3308 def test_get_all_snapshots_sort_dir_invalid(self): 

3309 self.mock_object( 

3310 db_api, 'share_snapshot_get_all_by_project', 

3311 mock.Mock(return_value=_FAKE_LIST_OF_ALL_SNAPSHOTS[0])) 

3312 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

3313 self.assertRaises( 

3314 exception.InvalidInput, 

3315 self.api.get_all_snapshots, 

3316 ctx, 

3317 sort_dir=1, 

3318 ) 

3319 share_api.policy.check_policy.assert_called_once_with( 

3320 ctx, 'share_snapshot', 'get_all_snapshots') 

3321 

3322 def test_allow_access_rule_already_exists(self): 

3323 share = db_utils.create_share(status=constants.STATUS_AVAILABLE) 

3324 fake_access = db_utils.create_access(share_id=share['id']) 

3325 self.mock_object(self.api.db, 'share_access_create') 

3326 

3327 self.assertRaises( 

3328 exception.ShareAccessExists, self.api.allow_access, 

3329 self.context, share, fake_access['access_type'], 

3330 fake_access['access_to'], fake_access['access_level']) 

3331 self.assertFalse(self.api.db.share_access_create.called) 

3332 

3333 def test_allow_access_invalid_access_level(self): 

3334 share = db_utils.create_share(status=constants.STATUS_AVAILABLE) 

3335 self.mock_object(self.api.db, 'share_access_create') 

3336 

3337 self.assertRaises( 

3338 exception.InvalidShareAccess, self.api.allow_access, 

3339 self.context, share, 'user', 'alice', access_level='execute') 

3340 self.assertFalse(self.api.db.share_access_create.called) 

3341 

3342 @ddt.data({'host': None}, 

3343 {'status': constants.STATUS_ERROR_DELETING, 

3344 'access_rules_status': constants.STATUS_ACTIVE}, 

3345 {'host': None, 'access_rules_status': constants.STATUS_ERROR}, 

3346 {'access_rules_status': constants.STATUS_ERROR}) 

3347 def test_allow_access_invalid_instance(self, params): 

3348 share = db_utils.create_share(host='fake') 

3349 db_utils.create_share_instance(share_id=share['id']) 

3350 db_utils.create_share_instance(share_id=share['id'], **params) 

3351 self.mock_object(self.api.db, 'share_access_create') 

3352 

3353 self.assertRaises(exception.InvalidShare, self.api.allow_access, 

3354 self.context, share, 'ip', '10.0.0.1') 

3355 self.assertFalse(self.api.db.share_access_create.called) 

3356 

3357 @ddt.data(*(constants.ACCESS_LEVELS + (None,))) 

3358 def test_allow_access(self, level): 

3359 share = db_utils.create_share(status=constants.STATUS_AVAILABLE) 

3360 values = { 

3361 'share_id': share['id'], 

3362 'access_type': 'fake_access_type', 

3363 'access_to': 'fake_access_to', 

3364 'access_level': level, 

3365 'metadata': None, 

3366 } 

3367 fake_access = copy.deepcopy(values) 

3368 fake_access.update({ 

3369 'id': 'fake_access_id', 

3370 'state': constants.STATUS_ACTIVE, 

3371 'deleted': 'fake_deleted', 

3372 'deleted_at': 'fake_deleted_at', 

3373 'instance_mappings': ['foo', 'bar'], 

3374 }) 

3375 self.mock_object(db_api, 'share_get', 

3376 mock.Mock(return_value=share)) 

3377 self.mock_object(db_api, 'share_access_create', 

3378 mock.Mock(return_value=fake_access)) 

3379 self.mock_object(db_api, 'share_access_get', 

3380 mock.Mock(return_value=fake_access)) 

3381 self.mock_object(db_api, 'share_access_get_all_by_type_and_access', 

3382 mock.Mock(return_value=[])) 

3383 self.mock_object(self.api, 'allow_access_to_instance') 

3384 

3385 access = self.api.allow_access( 

3386 self.context, share, fake_access['access_type'], 

3387 fake_access['access_to'], level) 

3388 

3389 self.assertEqual(fake_access, access) 

3390 db_api.share_access_create.assert_called_once_with( 

3391 self.context, values) 

3392 self.api.allow_access_to_instance.assert_called_once_with( 

3393 self.context, share.instance) 

3394 

3395 def test_allow_access_to_instance(self): 

3396 share = db_utils.create_share(host='fake') 

3397 rpc_method = self.mock_object(self.api.share_rpcapi, 'update_access') 

3398 

3399 self.api.allow_access_to_instance(self.context, share.instance) 

3400 

3401 rpc_method.assert_called_once_with(self.context, share.instance) 

3402 

3403 @ddt.data({'host': None}, 

3404 {'status': constants.STATUS_ERROR_DELETING, 

3405 'access_rules_status': constants.STATUS_ACTIVE}, 

3406 {'host': None, 'access_rules_status': constants.STATUS_ERROR}, 

3407 {'access_rules_status': constants.STATUS_ERROR}) 

3408 def test_deny_access_invalid_instance(self, params): 

3409 share = db_utils.create_share(host='fake') 

3410 db_utils.create_share_instance(share_id=share['id']) 

3411 db_utils.create_share_instance(share_id=share['id'], **params) 

3412 access_rule = db_utils.create_access(share_id=share['id']) 

3413 self.mock_object(self.api, 'deny_access_to_instance') 

3414 

3415 self.assertRaises(exception.InvalidShare, self.api.deny_access, 

3416 self.context, share, access_rule) 

3417 self.assertFalse(self.api.deny_access_to_instance.called) 

3418 

3419 def test_deny_access(self): 

3420 share = db_utils.create_share( 

3421 host='fake', status=constants.STATUS_AVAILABLE, 

3422 access_rules_status=constants.STATUS_ACTIVE) 

3423 access_rule = db_utils.create_access(share_id=share['id']) 

3424 self.mock_object(self.api, 'deny_access_to_instance') 

3425 

3426 retval = self.api.deny_access(self.context, share, access_rule) 

3427 

3428 self.assertIsNone(retval) 

3429 self.api.deny_access_to_instance.assert_called_once_with( 

3430 self.context, share.instance, access_rule) 

3431 

3432 def test_deny_access_to_instance(self): 

3433 share = db_utils.create_share(host='fake') 

3434 share_instance = db_utils.create_share_instance( 

3435 share_id=share['id'], host='fake') 

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

3437 rpc_method = self.mock_object(self.api.share_rpcapi, 'update_access') 

3438 self.mock_object(db_api, 'share_instance_access_get', 

3439 mock.Mock(return_value=access.instance_mappings[0])) 

3440 mock_share_instance_rules_status_update = self.mock_object( 

3441 self.api.access_helper, 

3442 'get_and_update_share_instance_access_rules_status') 

3443 mock_access_rule_state_update = self.mock_object( 

3444 self.api.access_helper, 

3445 'get_and_update_share_instance_access_rule') 

3446 

3447 self.api.deny_access_to_instance(self.context, share_instance, access) 

3448 

3449 rpc_method.assert_called_once_with(self.context, share_instance) 

3450 mock_access_rule_state_update.assert_called_once_with( 

3451 self.context, access['id'], 

3452 updates={'state': constants.ACCESS_STATE_QUEUED_TO_DENY}, 

3453 share_instance_id=share_instance['id']) 

3454 expected_conditional_change = { 

3455 constants.STATUS_ACTIVE: constants.SHARE_INSTANCE_RULES_SYNCING, 

3456 } 

3457 mock_share_instance_rules_status_update.assert_called_once_with( 

3458 self.context, share_instance_id=share_instance['id'], 

3459 conditionally_change=expected_conditional_change) 

3460 

3461 def test_access_get(self): 

3462 with mock.patch.object(db_api, 'share_access_get', 

3463 mock.Mock(return_value={'share_id': 'fake'})): 

3464 self.mock_object(self.api, 'get') 

3465 rule = self.api.access_get(self.context, 'fakeid') 

3466 self.assertEqual({'share_id': 'fake'}, rule) 

3467 db_api.share_access_get.assert_called_once_with( 

3468 self.context, 'fakeid') 

3469 self.api.get.assert_called_once_with(self.context, 'fake') 

3470 

3471 def test_access_get_all(self): 

3472 share = db_utils.create_share(id='fakeid') 

3473 

3474 values = { 

3475 'fakeacc0id': { 

3476 'id': 'fakeacc0id', 

3477 'access_type': 'fakeacctype', 

3478 'access_to': 'fakeaccto', 

3479 'access_level': 'rw', 

3480 'share_id': share['id'], 

3481 }, 

3482 'fakeacc1id': { 

3483 'id': 'fakeacc1id', 

3484 'access_type': 'fakeacctype', 

3485 'access_to': 'fakeaccto', 

3486 'access_level': 'rw', 

3487 'share_id': share['id'], 

3488 }, 

3489 } 

3490 rules = [ 

3491 db_utils.create_access(**values['fakeacc0id']), 

3492 db_utils.create_access(**values['fakeacc1id']), 

3493 ] 

3494 

3495 # add state property 

3496 values['fakeacc0id']['state'] = constants.STATUS_ACTIVE 

3497 values['fakeacc1id']['state'] = constants.STATUS_ACTIVE 

3498 

3499 self.mock_object(db_api, 'share_access_get_all_for_share', 

3500 mock.Mock(return_value=rules)) 

3501 actual = self.api.access_get_all(self.context, share) 

3502 

3503 self.assertEqual(rules, actual) 

3504 share_api.policy.check_policy.assert_called_once_with( 

3505 self.context, 'share', 'access_get_all') 

3506 db_api.share_access_get_all_for_share.assert_called_once_with( 

3507 self.context, 'fakeid', filters=None) 

3508 

3509 def test_share_metadata_get(self): 

3510 metadata = {'a': 'b', 'c': 'd'} 

3511 share_id = uuidutils.generate_uuid() 

3512 db_api.share_create(self.context, 

3513 {'id': share_id, 'metadata': metadata}) 

3514 self.assertEqual(metadata, 

3515 db_api.share_metadata_get(self.context, share_id)) 

3516 

3517 def test_share_metadata_update(self): 

3518 metadata1 = {'a': '1', 'c': '2'} 

3519 metadata2 = {'a': '3', 'd': '5'} 

3520 should_be = {'a': '3', 'c': '2', 'd': '5'} 

3521 share_id = uuidutils.generate_uuid() 

3522 db_api.share_create(self.context, 

3523 {'id': share_id, 'metadata': metadata1}) 

3524 db_api.share_metadata_update(self.context, share_id, metadata2, False) 

3525 self.assertEqual(should_be, 

3526 db_api.share_metadata_get(self.context, share_id)) 

3527 

3528 def test_share_metadata_update_delete(self): 

3529 metadata1 = {'a': '1', 'c': '2'} 

3530 metadata2 = {'a': '3', 'd': '4'} 

3531 should_be = metadata2 

3532 share_id = uuidutils.generate_uuid() 

3533 db_api.share_create(self.context, 

3534 {'id': share_id, 'metadata': metadata1}) 

3535 db_api.share_metadata_update(self.context, share_id, metadata2, True) 

3536 self.assertEqual(should_be, 

3537 db_api.share_metadata_get(self.context, share_id)) 

3538 

3539 def test_extend_invalid_status(self): 

3540 invalid_status = 'fake' 

3541 share = db_utils.create_share(status=invalid_status) 

3542 new_size = 123 

3543 

3544 self.assertRaises(exception.InvalidShare, 

3545 self.api.extend, self.context, share, new_size) 

3546 

3547 def test_extend_invalid_task_state(self): 

3548 share = db_utils.create_share( 

3549 status=constants.STATUS_AVAILABLE, 

3550 task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS) 

3551 new_size = 123 

3552 

3553 self.assertRaises(exception.ShareBusyException, 

3554 self.api.extend, self.context, share, new_size) 

3555 

3556 def test_extend_invalid_size(self): 

3557 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3558 size=200) 

3559 new_size = 123 

3560 

3561 self.assertRaises(exception.InvalidInput, 

3562 self.api.extend, self.context, share, new_size) 

3563 

3564 def test_extend_share_over_per_share_quota(self): 

3565 quota.CONF.set_default("per_share_gigabytes", 5, 'quota') 

3566 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3567 size=4) 

3568 new_size = 6 

3569 self.assertRaises(exception.ShareSizeExceedsLimit, 

3570 self.api.extend, self.context, share, new_size) 

3571 

3572 def test_extend_with_share_type_size_limit(self): 

3573 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 

3574 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3575 size=3) 

3576 self.mock_object(share_types, 'get_share_type', 

3577 mock.Mock(return_value=self.sized_sha_type)) 

3578 self.mock_policy_check = self.mock_object( 

3579 policy, 'check_policy', mock.Mock(return_value=False)) 

3580 

3581 new_size = 5 

3582 

3583 self.assertRaises(exception.InvalidInput, 

3584 self.api.extend, ctx, 

3585 share, new_size) 

3586 

3587 def test_extend_with_share_type_size_limit_admin(self): 

3588 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True) 

3589 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3590 size=3) 

3591 self.mock_object(share_types, 'get_share_type', 

3592 mock.Mock(return_value=self.sized_sha_type)) 

3593 self.mock_policy_check = self.mock_object( 

3594 policy, 'check_policy', mock.Mock(return_value=True)) 

3595 

3596 new_size = 7 

3597 

3598 self.assertRaises(exception.InvalidInput, 

3599 self.api.extend, ctx, 

3600 share, new_size) 

3601 

3602 def _setup_extend_mocks(self, supports_replication): 

3603 replica_list = [] 

3604 if supports_replication: 

3605 replica_list.append({'id': 'fake_replica_id'}) 

3606 replica_list.append({'id': 'fake_replica_id_2'}) 

3607 self.mock_object(db_api, 'share_replicas_get_all_by_share', 

3608 mock.Mock(return_value=replica_list)) 

3609 

3610 @ddt.data( 

3611 (False, 'gigabytes', exception.ShareSizeExceedsAvailableQuota), 

3612 (True, 'replica_gigabytes', 

3613 exception.ShareReplicaSizeExceedsAvailableQuota) 

3614 ) 

3615 @ddt.unpack 

3616 def test_extend_quota_error(self, supports_replication, quota_key, 

3617 expected_exception): 

3618 self._setup_extend_mocks(supports_replication) 

3619 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3620 size=100) 

3621 new_size = 123 

3622 replica_amount = len( 

3623 db_api.share_replicas_get_all_by_share.return_value) 

3624 value_to_be_extended = new_size - share['size'] 

3625 usages = {quota_key: {'reserved': 11, 'in_use': 12}} 

3626 quotas = {quota_key: 13} 

3627 overs = {quota_key: new_size} 

3628 exc = exception.OverQuota(usages=usages, quotas=quotas, overs=overs) 

3629 expected_deltas = { 

3630 'project_id': share['project_id'], 

3631 'gigabytes': value_to_be_extended, 

3632 'user_id': share['user_id'], 

3633 'share_type_id': share['instance']['share_type_id'] 

3634 } 

3635 if supports_replication: 

3636 expected_deltas.update( 

3637 {'replica_gigabytes': value_to_be_extended * replica_amount}) 

3638 self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc)) 

3639 

3640 self.assertRaises(expected_exception, 

3641 self.api.extend, self.context, share, new_size) 

3642 quota.QUOTAS.reserve.assert_called_once_with( 

3643 mock.ANY, **expected_deltas 

3644 ) 

3645 

3646 def test_extend_quota_user(self): 

3647 self._setup_extend_mocks(False) 

3648 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3649 size=100) 

3650 diff_user_context = context.RequestContext( 

3651 user_id='fake2', 

3652 project_id='fake', 

3653 is_admin=False 

3654 ) 

3655 fake_type = { 

3656 'id': 'fake_type_id', 

3657 'extra_specs': { 

3658 'snapshot_support': False, 

3659 'create_share_from_snapshot_support': False, 

3660 'driver_handles_share_servers': False, 

3661 }, 

3662 } 

3663 new_size = 123 

3664 size_increase = int(new_size) - share['size'] 

3665 self.mock_object(quota.QUOTAS, 'reserve') 

3666 self.mock_object(share_types, 'get_share_type', 

3667 mock.Mock(return_value=fake_type)) 

3668 

3669 self.api.extend(diff_user_context, share, new_size) 

3670 

3671 quota.QUOTAS.reserve.assert_called_once_with( 

3672 diff_user_context, 

3673 project_id=share['project_id'], 

3674 gigabytes=size_increase, 

3675 share_type_id=None, 

3676 user_id=share['user_id'] 

3677 ) 

3678 

3679 @ddt.data(True, False) 

3680 def test_extend_valid(self, supports_replication): 

3681 self._setup_extend_mocks(supports_replication) 

3682 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3683 size=100) 

3684 new_size = 123 

3685 size_increase = int(new_size) - share['size'] 

3686 replica_amount = len( 

3687 db_api.share_replicas_get_all_by_share.return_value) 

3688 

3689 expected_deltas = { 

3690 'project_id': share['project_id'], 

3691 'gigabytes': size_increase, 

3692 'user_id': share['user_id'], 

3693 'share_type_id': share['instance']['share_type_id'] 

3694 } 

3695 if supports_replication: 

3696 new_replica_size = size_increase * replica_amount 

3697 expected_deltas.update({'replica_gigabytes': new_replica_size}) 

3698 self.mock_object(self.api, 'update') 

3699 self.mock_object(self.api.scheduler_rpcapi, 'extend_share') 

3700 self.mock_object(quota.QUOTAS, 'reserve') 

3701 self.mock_object(share_types, 'get_share_type') 

3702 self.mock_object(share_types, 'provision_filter_on_size') 

3703 self.mock_object(self.api, '_get_request_spec_dict') 

3704 

3705 self.api.extend(self.context, share, new_size) 

3706 

3707 self.api.update.assert_called_once_with( 

3708 self.context, share, {'status': constants.STATUS_EXTENDING}) 

3709 

3710 self.api.scheduler_rpcapi.extend_share.assert_called_once_with( 

3711 self.context, share['id'], new_size, mock.ANY, mock.ANY 

3712 ) 

3713 quota.QUOTAS.reserve.assert_called_once_with( 

3714 self.context, **expected_deltas) 

3715 

3716 def test_shrink_invalid_status(self): 

3717 invalid_status = 'fake' 

3718 share = db_utils.create_share(status=invalid_status) 

3719 

3720 self.assertRaises(exception.InvalidShare, 

3721 self.api.shrink, self.context, share, 123) 

3722 

3723 def test_shrink_invalid_task_state(self): 

3724 share = db_utils.create_share( 

3725 status=constants.STATUS_AVAILABLE, 

3726 task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS) 

3727 

3728 self.assertRaises(exception.ShareBusyException, 

3729 self.api.shrink, self.context, share, 123) 

3730 

3731 @ddt.data(300, 0, -1) 

3732 def test_shrink_invalid_size(self, new_size): 

3733 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3734 size=200) 

3735 

3736 self.assertRaises(exception.InvalidInput, 

3737 self.api.shrink, self.context, share, new_size) 

3738 

3739 @ddt.data(constants.STATUS_AVAILABLE, 

3740 constants.STATUS_SHRINKING_POSSIBLE_DATA_LOSS_ERROR) 

3741 def test_shrink_valid(self, share_status): 

3742 share = db_utils.create_share(status=share_status, size=100) 

3743 new_size = 50 

3744 self.mock_object(self.api, 'update') 

3745 self.mock_object(self.api.share_rpcapi, 'shrink_share') 

3746 

3747 self.api.shrink(self.context, share, new_size) 

3748 

3749 self.api.update.assert_called_once_with( 

3750 self.context, share, {'status': constants.STATUS_SHRINKING}) 

3751 self.api.share_rpcapi.shrink_share.assert_called_once_with( 

3752 self.context, share, new_size 

3753 ) 

3754 

3755 def test_shrink_with_share_type_size_limit(self): 

3756 share = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

3757 size=3) 

3758 self.mock_object(share_types, 'get_share_type', 

3759 mock.Mock(return_value=self.sized_sha_type)) 

3760 new_size = 1 

3761 

3762 self.assertRaises(exception.InvalidInput, 

3763 self.api.shrink, self.context, 

3764 share, new_size) 

3765 

3766 def test_snapshot_allow_access(self): 

3767 access_to = '1.1.1.1' 

3768 access_type = 'ip' 

3769 share = db_utils.create_share() 

3770 snapshot = db_utils.create_snapshot(share_id=share['id'], 

3771 status=constants.STATUS_AVAILABLE) 

3772 access = db_utils.create_snapshot_access( 

3773 share_snapshot_id=snapshot['id']) 

3774 values = {'share_snapshot_id': snapshot['id'], 

3775 'access_type': access_type, 

3776 'access_to': access_to} 

3777 

3778 existing_access_check = self.mock_object( 

3779 db_api, 'share_snapshot_check_for_existing_access', 

3780 mock.Mock(return_value=False)) 

3781 access_create = self.mock_object( 

3782 db_api, 'share_snapshot_access_create', 

3783 mock.Mock(return_value=access)) 

3784 self.mock_object(self.api.share_rpcapi, 'snapshot_update_access') 

3785 

3786 out = self.api.snapshot_allow_access(self.context, snapshot, 

3787 access_type, access_to) 

3788 

3789 self.assertEqual(access, out) 

3790 existing_access_check.assert_called_once_with( 

3791 utils.IsAMatcher(context.RequestContext), snapshot['id'], 

3792 access_type, access_to) 

3793 access_create.assert_called_once_with( 

3794 utils.IsAMatcher(context.RequestContext), values) 

3795 

3796 def test_snapshot_allow_access_instance_exception(self): 

3797 access_to = '1.1.1.1' 

3798 access_type = 'ip' 

3799 share = db_utils.create_share() 

3800 snapshot = db_utils.create_snapshot(share_id=share['id']) 

3801 existing_access_check = self.mock_object( 

3802 db_api, 'share_snapshot_check_for_existing_access', 

3803 mock.Mock(return_value=False)) 

3804 

3805 self.assertRaises(exception.InvalidShareSnapshotInstance, 

3806 self.api.snapshot_allow_access, self.context, 

3807 snapshot, access_type, access_to) 

3808 

3809 existing_access_check.assert_called_once_with( 

3810 utils.IsAMatcher(context.RequestContext), snapshot['id'], 

3811 access_type, access_to) 

3812 

3813 def test_snapshot_allow_access_access_exists_exception(self): 

3814 access_to = '1.1.1.1' 

3815 access_type = 'ip' 

3816 share = db_utils.create_share() 

3817 snapshot = db_utils.create_snapshot(share_id=share['id']) 

3818 db_utils.create_snapshot_access( 

3819 share_snapshot_id=snapshot['id'], access_to=access_to, 

3820 access_type=access_type) 

3821 

3822 existing_access_check = self.mock_object( 

3823 db_api, 'share_snapshot_check_for_existing_access', 

3824 mock.Mock(return_value=True)) 

3825 

3826 self.assertRaises(exception.ShareSnapshotAccessExists, 

3827 self.api.snapshot_allow_access, self.context, 

3828 snapshot, access_type, access_to) 

3829 

3830 existing_access_check.assert_called_once_with( 

3831 utils.IsAMatcher(context.RequestContext), snapshot['id'], 

3832 access_type, access_to) 

3833 

3834 def test_snapshot_deny_access(self): 

3835 share = db_utils.create_share() 

3836 snapshot = db_utils.create_snapshot(share_id=share['id'], 

3837 status=constants.STATUS_AVAILABLE) 

3838 access = db_utils.create_snapshot_access( 

3839 share_snapshot_id=snapshot['id']) 

3840 mapping = {'id': 'fake_id', 

3841 'state': constants.STATUS_ACTIVE, 

3842 'access_id': access['id']} 

3843 

3844 access_get = self.mock_object( 

3845 db_api, 'share_snapshot_instance_access_get', 

3846 mock.Mock(return_value=mapping)) 

3847 access_update_state = self.mock_object( 

3848 db_api, 'share_snapshot_instance_access_update') 

3849 update_access = self.mock_object(self.api.share_rpcapi, 

3850 'snapshot_update_access') 

3851 

3852 self.api.snapshot_deny_access(self.context, snapshot, access) 

3853 

3854 access_get.assert_called_once_with( 

3855 utils.IsAMatcher(context.RequestContext), access['id'], 

3856 snapshot['instance']['id']) 

3857 access_update_state.assert_called_once_with( 

3858 utils.IsAMatcher(context.RequestContext), access['id'], 

3859 snapshot.instance['id'], 

3860 {'state': constants.ACCESS_STATE_QUEUED_TO_DENY}) 

3861 update_access.assert_called_once_with( 

3862 utils.IsAMatcher(context.RequestContext), snapshot['instance']) 

3863 

3864 def test_snapshot_deny_access_exception(self): 

3865 share = db_utils.create_share() 

3866 snapshot = db_utils.create_snapshot(share_id=share['id']) 

3867 access = db_utils.create_snapshot_access( 

3868 share_snapshot_id=snapshot['id']) 

3869 

3870 self.assertRaises(exception.InvalidShareSnapshotInstance, 

3871 self.api.snapshot_deny_access, self.context, 

3872 snapshot, access) 

3873 

3874 def test_snapshot_access_get_all(self): 

3875 share = db_utils.create_share() 

3876 snapshot = db_utils.create_snapshot(share_id=share['id']) 

3877 access = [] 

3878 access.append(db_utils.create_snapshot_access( 

3879 share_snapshot_id=snapshot['id'])) 

3880 

3881 self.mock_object( 

3882 db_api, 'share_snapshot_access_get_all_for_share_snapshot', 

3883 mock.Mock(return_value=access)) 

3884 

3885 out = self.api.snapshot_access_get_all(self.context, snapshot) 

3886 

3887 self.assertEqual(access, out) 

3888 

3889 def test_snapshot_access_get(self): 

3890 share = db_utils.create_share() 

3891 snapshot = db_utils.create_snapshot(share_id=share['id']) 

3892 access = db_utils.create_snapshot_access( 

3893 share_snapshot_id=snapshot['id']) 

3894 

3895 self.mock_object( 

3896 db_api, 'share_snapshot_access_get', 

3897 mock.Mock(return_value=access)) 

3898 

3899 out = self.api.snapshot_access_get(self.context, access['id']) 

3900 

3901 self.assertEqual(access, out) 

3902 

3903 def test_snapshot_export_locations_get(self): 

3904 share = db_utils.create_share() 

3905 snapshot = db_utils.create_snapshot(share_id=share['id']) 

3906 

3907 self.mock_object( 

3908 db_api, 'share_snapshot_export_locations_get', 

3909 mock.Mock(return_value='')) 

3910 

3911 out = self.api.snapshot_export_locations_get(self.context, snapshot) 

3912 

3913 self.assertEqual('', out) 

3914 

3915 def test_snapshot_export_location_get(self): 

3916 fake_el = '/fake_export_location' 

3917 

3918 self.mock_object( 

3919 db_api, 'share_snapshot_instance_export_location_get', 

3920 mock.Mock(return_value=fake_el)) 

3921 

3922 out = self.api.snapshot_export_location_get(self.context, 'fake_id') 

3923 

3924 self.assertEqual(fake_el, out) 

3925 

3926 @ddt.data(True, False) 

3927 def test__modify_quotas_for_share_migration(self, new_replication_type): 

3928 extra_specs = ( 

3929 {'replication_type': 'readable'} if new_replication_type else {}) 

3930 share = db_utils.create_share() 

3931 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

3932 

3933 expected_deltas = { 

3934 'project_id': share['project_id'], 

3935 'user_id': share['user_id'], 

3936 'shares': 1, 

3937 'gigabytes': share['size'], 

3938 'share_type_id': share_type['id'] 

3939 } 

3940 

3941 if new_replication_type: 

3942 expected_deltas.update({ 

3943 'share_replicas': 1, 

3944 'replica_gigabytes': share['size'], 

3945 }) 

3946 reservations = 'reservations' 

3947 

3948 mock_specs_get = self.mock_object( 

3949 self.api, 'get_share_attributes_from_share_type', 

3950 mock.Mock(return_value=extra_specs)) 

3951 mock_reserve = self.mock_object( 

3952 quota.QUOTAS, 'reserve', mock.Mock(return_value=reservations)) 

3953 mock_commit = self.mock_object(quota.QUOTAS, 'commit') 

3954 

3955 self.api._modify_quotas_for_share_migration( 

3956 self.context, share, share_type) 

3957 

3958 mock_specs_get.assert_called_once_with(share_type) 

3959 mock_reserve.assert_called_once_with( 

3960 self.context, **expected_deltas) 

3961 mock_commit.assert_called_once_with( 

3962 self.context, reservations, project_id=share['project_id'], 

3963 user_id=share['user_id'], share_type_id=share_type['id']) 

3964 

3965 @ddt.data( 

3966 ('replica_gigabytes', exception.ShareReplicaSizeExceedsAvailableQuota), 

3967 ('share_replicas', exception.ShareReplicasLimitExceeded), 

3968 ('gigabytes', exception.ShareSizeExceedsAvailableQuota) 

3969 ) 

3970 @ddt.unpack 

3971 def test__modify_quotas_for_share_migration_reservation_failed( 

3972 self, over_resource, expected_exception): 

3973 extra_specs = {'replication_type': 'readable'} 

3974 share = db_utils.create_share() 

3975 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

3976 expected_deltas = { 

3977 'project_id': share['project_id'], 

3978 'user_id': share['user_id'], 

3979 'share_replicas': 1, 

3980 'shares': 1, 

3981 'gigabytes': share['size'], 

3982 'replica_gigabytes': share['size'], 

3983 'share_type_id': share_type['id'] 

3984 } 

3985 usages = { 

3986 over_resource: { 

3987 'reserved': 'fake', 

3988 'in_use': 'fake' 

3989 } 

3990 } 

3991 quotas = { 

3992 over_resource: 'fake' 

3993 } 

3994 

3995 effect_exc = exception.OverQuota( 

3996 overs=[over_resource], usages=usages, quotas=quotas) 

3997 mock_specs_get = self.mock_object( 

3998 self.api, 'get_share_attributes_from_share_type', 

3999 mock.Mock(return_value=extra_specs)) 

4000 mock_reserve = self.mock_object( 

4001 quota.QUOTAS, 'reserve', mock.Mock(side_effect=effect_exc)) 

4002 

4003 self.assertRaises( 

4004 expected_exception, 

4005 self.api._modify_quotas_for_share_migration, 

4006 self.context, share, share_type 

4007 ) 

4008 

4009 mock_specs_get.assert_called_once_with(share_type) 

4010 mock_reserve.assert_called_once_with(self.context, **expected_deltas) 

4011 

4012 @ddt.data({'share_type': True, 'share_net': True, 'dhss': True}, 

4013 {'share_type': False, 'share_net': True, 'dhss': True}, 

4014 {'share_type': False, 'share_net': False, 'dhss': True}, 

4015 {'share_type': True, 'share_net': False, 'dhss': False}, 

4016 {'share_type': False, 'share_net': False, 'dhss': False}) 

4017 @ddt.unpack 

4018 def test_migration_start(self, share_type, share_net, dhss): 

4019 host = 'fake2@backend#pool' 

4020 service = {'availability_zone_id': 'fake_az_id', 

4021 'availability_zone': {'name': 'fake_az1'}} 

4022 share_network = None 

4023 share_network_id = None 

4024 if share_net: 

4025 share_network = db_utils.create_share_network(id='fake_net_id') 

4026 share_network_id = share_network['id'] 

4027 

4028 fake_type = { 

4029 'id': 'fake_type_id', 

4030 'extra_specs': { 

4031 'snapshot_support': False, 

4032 'create_share_from_snapshot_support': False, 

4033 'revert_to_snapshot_support': False, 

4034 'mount_snapshot_support': False, 

4035 'mount_point_name_support': False, 

4036 'driver_handles_share_servers': dhss, 

4037 }, 

4038 } 

4039 

4040 if share_type: 

4041 fake_type_2 = { 

4042 'id': 'fake_type_2_id', 

4043 'extra_specs': { 

4044 'snapshot_support': False, 

4045 'create_share_from_snapshot_support': False, 

4046 'revert_to_snapshot_support': False, 

4047 'mount_snapshot_support': False, 

4048 'mount_point_name_support': False, 

4049 'driver_handles_share_servers': dhss, 

4050 'availability_zones': 'fake_az1,fake_az2', 

4051 }, 

4052 } 

4053 else: 

4054 fake_type_2 = fake_type 

4055 

4056 share = db_utils.create_share( 

4057 status=constants.STATUS_AVAILABLE, 

4058 host='fake@backend#pool', share_type_id=fake_type['id'], 

4059 share_network_id=share_network_id) 

4060 

4061 request_spec = self._get_request_spec_dict( 

4062 share, fake_type_2, self.context, size=0, 

4063 availability_zone_id='fake_az_id', 

4064 share_network_id=share_network_id) 

4065 

4066 self.mock_object(self.scheduler_rpcapi, 'migrate_share_to_host') 

4067 self.mock_object(share_types, 'get_share_type', 

4068 mock.Mock(return_value=fake_type)) 

4069 self.mock_object(utils, 'validate_service_host') 

4070 self.mock_object(db_api, 'share_instance_update') 

4071 self.mock_object(db_api, 'share_update') 

4072 self.mock_object(db_api, 'service_get_by_args', 

4073 mock.Mock(return_value=service)) 

4074 self.mock_object(share_api.API, '_modify_quotas_for_share_migration') 

4075 

4076 if share_type: 

4077 self.api.migration_start(self.context, share, host, False, True, 

4078 True, True, True, share_network, 

4079 fake_type_2) 

4080 else: 

4081 self.api.migration_start(self.context, share, host, False, True, 

4082 True, True, True, share_network, None) 

4083 

4084 self.scheduler_rpcapi.migrate_share_to_host.assert_called_once_with( 

4085 self.context, share['id'], host, False, True, True, True, True, 

4086 share_network_id, fake_type_2['id'], request_spec) 

4087 if not share_type: 

4088 share_types.get_share_type.assert_called_once_with( 

4089 self.context, fake_type['id']) 

4090 utils.validate_service_host.assert_called_once_with( 

4091 self.context, 'fake2@backend') 

4092 db_api.service_get_by_args.assert_called_once_with( 

4093 self.context, 'fake2@backend', 'manila-share') 

4094 db_api.share_update.assert_called_once_with( 

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

4096 {'task_state': constants.TASK_STATE_MIGRATION_STARTING}) 

4097 db_api.share_instance_update.assert_called_once_with( 

4098 self.context, share.instance['id'], 

4099 {'status': constants.STATUS_MIGRATING}) 

4100 if share_type: 

4101 (share_api.API._modify_quotas_for_share_migration. 

4102 assert_called_once_with(self.context, share, fake_type_2)) 

4103 

4104 def test_migration_start_with_new_share_type_limit(self): 

4105 host = 'fake2@backend#pool' 

4106 self.mock_object(utils, 'validate_service_host') 

4107 share = db_utils.create_share( 

4108 status=constants.STATUS_AVAILABLE, 

4109 size=1) 

4110 self.assertRaises(exception.InvalidInput, 

4111 self.api.migration_start, 

4112 self.context, 

4113 share, host, False, True, 

4114 True, True, True, None, 

4115 self.sized_sha_type) 

4116 

4117 def test_migration_start_destination_az_unsupported(self): 

4118 host = 'fake2@backend#pool' 

4119 host_without_pool = host.split('#')[0] 

4120 service = {'availability_zone_id': 'fake_az_id', 

4121 'availability_zone': {'name': 'fake_az3'}} 

4122 share_network = db_utils.create_share_network(id='fake_net_id') 

4123 share_network_id = share_network['id'] 

4124 existing_share_type = { 

4125 'id': '4b5b0920-a294-401b-bb7d-c55b425e1cad', 

4126 'name': 'fake_type_1', 

4127 'extra_specs': { 

4128 'snapshot_support': False, 

4129 'create_share_from_snapshot_support': False, 

4130 'revert_to_snapshot_support': False, 

4131 'mount_snapshot_support': False, 

4132 'mount_point_name_support': False, 

4133 'driver_handles_share_servers': 'true', 

4134 'availability_zones': 'fake_az3' 

4135 }, 

4136 } 

4137 new_share_type = { 

4138 'id': 'fa844ae2-494d-4da9-95e7-37ac6a26f635', 

4139 'name': 'fake_type_2', 

4140 'extra_specs': { 

4141 'snapshot_support': False, 

4142 'create_share_from_snapshot_support': False, 

4143 'revert_to_snapshot_support': False, 

4144 'mount_snapshot_support': False, 

4145 'mount_point_name_support': False, 

4146 'driver_handles_share_servers': 'true', 

4147 'availability_zones': 'fake_az1,fake_az2', 

4148 }, 

4149 } 

4150 share = db_utils.create_share( 

4151 status=constants.STATUS_AVAILABLE, 

4152 host='fake@backend#pool', share_type_id=existing_share_type['id'], 

4153 share_network_id=share_network_id) 

4154 self.mock_object(self.api, '_get_request_spec_dict') 

4155 self.mock_object(self.scheduler_rpcapi, 'migrate_share_to_host') 

4156 self.mock_object(share_types, 'get_share_type') 

4157 self.mock_object(utils, 'validate_service_host') 

4158 self.mock_object(db_api, 'share_instance_update') 

4159 self.mock_object(db_api, 'share_update') 

4160 self.mock_object(db_api, 'service_get_by_args', 

4161 mock.Mock(return_value=service)) 

4162 self.mock_object(share_api.API, '_modify_quotas_for_share_migration') 

4163 

4164 self.assertRaises(exception.InvalidShare, 

4165 self.api.migration_start, 

4166 self.context, share, host, False, True, True, 

4167 True, False, new_share_network=share_network, 

4168 new_share_type=new_share_type) 

4169 utils.validate_service_host.assert_called_once_with( 

4170 self.context, host_without_pool) 

4171 share_types.get_share_type.assert_not_called() 

4172 db_api.share_update.assert_not_called() 

4173 db_api.service_get_by_args.assert_called_once_with( 

4174 self.context, host_without_pool, 'manila-share') 

4175 self.api._get_request_spec_dict.assert_not_called() 

4176 db_api.share_instance_update.assert_not_called() 

4177 self.scheduler_rpcapi.migrate_share_to_host.assert_not_called() 

4178 

4179 @ddt.data({'force_host_assisted': True, 'writable': True, 

4180 'preserve_metadata': False, 'preserve_snapshots': False, 

4181 'nondisruptive': False}, 

4182 {'force_host_assisted': True, 'writable': False, 

4183 'preserve_metadata': True, 'preserve_snapshots': False, 

4184 'nondisruptive': False}, 

4185 {'force_host_assisted': True, 'writable': False, 

4186 'preserve_metadata': False, 'preserve_snapshots': True, 

4187 'nondisruptive': False}, 

4188 {'force_host_assisted': True, 'writable': False, 

4189 'preserve_metadata': False, 'preserve_snapshots': False, 

4190 'nondisruptive': True}) 

4191 @ddt.unpack 

4192 def test_migration_start_invalid_host_and_driver_assisted_params( 

4193 self, force_host_assisted, writable, preserve_metadata, 

4194 preserve_snapshots, nondisruptive): 

4195 

4196 self.assertRaises( 

4197 exception.InvalidInput, self.api.migration_start, self.context, 

4198 'some_share', 'some_host', force_host_assisted, preserve_metadata, 

4199 writable, preserve_snapshots, nondisruptive) 

4200 

4201 @ddt.data(True, False) 

4202 def test_migration_start_invalid_share_network_type_combo(self, dhss): 

4203 host = 'fake2@backend#pool' 

4204 share_network = None 

4205 if not dhss: 

4206 share_network = db_utils.create_share_network(id='fake_net_id') 

4207 

4208 fake_type = { 

4209 'id': 'fake_type_id', 

4210 'extra_specs': { 

4211 'snapshot_support': False, 

4212 'driver_handles_share_servers': not dhss, 

4213 }, 

4214 } 

4215 

4216 fake_type_2 = { 

4217 'id': 'fake_type_2_id', 

4218 'extra_specs': { 

4219 'snapshot_support': False, 

4220 'driver_handles_share_servers': dhss, 

4221 }, 

4222 } 

4223 

4224 share = db_utils.create_share( 

4225 status=constants.STATUS_AVAILABLE, 

4226 host='fake@backend#pool', share_type_id=fake_type['id']) 

4227 

4228 self.mock_object(utils, 'validate_service_host') 

4229 self.mock_object(share_api.API, '_modify_quotas_for_share_migration') 

4230 

4231 self.assertRaises( 

4232 exception.InvalidInput, self.api.migration_start, self.context, 

4233 share, host, False, True, True, True, True, share_network, 

4234 fake_type_2) 

4235 

4236 utils.validate_service_host.assert_called_once_with( 

4237 self.context, 'fake2@backend') 

4238 

4239 def test_migration_start_status_unavailable(self): 

4240 host = 'fake2@backend#pool' 

4241 share = db_utils.create_share( 

4242 status=constants.STATUS_ERROR) 

4243 

4244 self.assertRaises(exception.InvalidShare, self.api.migration_start, 

4245 self.context, share, host, False, True, True, True, 

4246 True) 

4247 

4248 def test_migration_start_access_rules_status_error(self): 

4249 host = 'fake2@backend#pool' 

4250 instance = db_utils.create_share_instance( 

4251 share_id='fake_share_id', 

4252 access_rules_status=constants.STATUS_ERROR, 

4253 status=constants.STATUS_AVAILABLE) 

4254 share = db_utils.create_share( 

4255 id='fake_share_id', 

4256 instances=[instance]) 

4257 

4258 self.assertRaises(exception.InvalidShare, self.api.migration_start, 

4259 self.context, share, host, False, True, True, True, 

4260 True) 

4261 

4262 def test_migration_start_task_state_invalid(self): 

4263 host = 'fake2@backend#pool' 

4264 share = db_utils.create_share( 

4265 status=constants.STATUS_AVAILABLE, 

4266 task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS) 

4267 

4268 self.assertRaises(exception.ShareBusyException, 

4269 self.api.migration_start, 

4270 self.context, share, host, False, True, True, True, 

4271 True) 

4272 

4273 def test_migration_start_host_assisted_with_snapshots(self): 

4274 host = 'fake2@backend#pool' 

4275 share = db_utils.create_share( 

4276 host='fake@backend#pool', status=constants.STATUS_AVAILABLE) 

4277 self.mock_object(db_api, 'share_snapshot_get_all_for_share', 

4278 mock.Mock(return_value=True)) 

4279 

4280 self.assertRaises(exception.Conflict, self.api.migration_start, 

4281 self.context, share, host, True, False, False, False, 

4282 False) 

4283 

4284 def test_migration_start_with_snapshots(self): 

4285 host = 'fake2@backend#pool' 

4286 

4287 fake_type = { 

4288 'id': 'fake_type_id', 

4289 'extra_specs': { 

4290 'snapshot_support': True, 

4291 'driver_handles_share_servers': False, 

4292 }, 

4293 } 

4294 

4295 service = {'availability_zone_id': 'fake_az_id', 

4296 'availability_zone': {'name': 'fake_az'}} 

4297 self.mock_object(db_api, 'service_get_by_args', 

4298 mock.Mock(return_value=service)) 

4299 self.mock_object(utils, 'validate_service_host') 

4300 self.mock_object(share_types, 'get_share_type', 

4301 mock.Mock(return_value=fake_type)) 

4302 

4303 share = db_utils.create_share( 

4304 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

4305 share_type_id=fake_type['id']) 

4306 

4307 request_spec = self._get_request_spec_dict( 

4308 share, fake_type, self.context, availability_zone_id='fake_az_id') 

4309 

4310 self.api.migration_start(self.context, share, host, False, True, True, 

4311 True, True) 

4312 

4313 self.scheduler_rpcapi.migrate_share_to_host.assert_called_once_with( 

4314 self.context, share['id'], host, False, True, True, True, True, 

4315 None, 'fake_type_id', request_spec) 

4316 

4317 def test_migration_start_has_replicas(self): 

4318 host = 'fake2@backend#pool' 

4319 share = db_utils.create_share( 

4320 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

4321 replication_type='dr') 

4322 for i in range(1, 4): 

4323 db_utils.create_share_replica( 

4324 share_id=share['id'], replica_state='in_sync') 

4325 self.mock_object(db_api, 'share_snapshot_get_all_for_share', 

4326 mock.Mock(return_value=True)) 

4327 mock_log = self.mock_object(share_api, 'LOG') 

4328 mock_snapshot_get_call = self.mock_object( 

4329 db_api, 'share_snapshot_get_all_for_share') 

4330 # Share was updated after adding replicas, grabbing it again. 

4331 share = db_api.share_get(self.context, share['id']) 

4332 

4333 self.assertRaises(exception.Conflict, self.api.migration_start, 

4334 self.context, share, host, False, True, True, True, 

4335 True) 

4336 self.assertTrue(mock_log.error.called) 

4337 self.assertFalse(mock_snapshot_get_call.called) 

4338 

4339 def test_migration_start_is_member_of_group(self): 

4340 group = db_utils.create_share_group() 

4341 share = db_utils.create_share( 

4342 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

4343 share_group_id=group['id']) 

4344 mock_log = self.mock_object(share_api, 'LOG') 

4345 

4346 self.assertRaises(exception.InvalidShare, self.api.migration_start, 

4347 self.context, share, 'fake_host', False, True, True, 

4348 True, True) 

4349 self.assertTrue(mock_log.error.called) 

4350 

4351 def test_migration_start_invalid_host(self): 

4352 host = 'fake@backend#pool' 

4353 share = db_utils.create_share( 

4354 host='fake2@backend', status=constants.STATUS_AVAILABLE) 

4355 

4356 self.mock_object(db_api, 'share_snapshot_get_all_for_share', 

4357 mock.Mock(return_value=False)) 

4358 

4359 self.assertRaises(exception.ServiceNotFound, 

4360 self.api.migration_start, 

4361 self.context, share, host, False, True, True, True, 

4362 True) 

4363 

4364 @ddt.data({'dhss': True, 'new_share_network_id': 'fake_net_id', 

4365 'new_share_type_id': 'fake_type_id'}, 

4366 {'dhss': False, 'new_share_network_id': None, 

4367 'new_share_type_id': 'fake_type_id'}, 

4368 {'dhss': True, 'new_share_network_id': 'fake_net_id', 

4369 'new_share_type_id': None}) 

4370 @ddt. unpack 

4371 def test_migration_start_same_data_as_source( 

4372 self, dhss, new_share_network_id, new_share_type_id): 

4373 host = 'fake@backend#pool' 

4374 

4375 fake_type_src = { 

4376 'id': 'fake_type_id', 

4377 'extra_specs': { 

4378 'snapshot_support': True, 

4379 'driver_handles_share_servers': True, 

4380 }, 

4381 } 

4382 

4383 new_share_type_param = None 

4384 if new_share_type_id: 

4385 new_share_type_param = { 

4386 'id': new_share_type_id, 

4387 'extra_specs': { 

4388 'snapshot_support': True, 

4389 'driver_handles_share_servers': dhss, 

4390 }, 

4391 } 

4392 

4393 new_share_net_param = None 

4394 if new_share_network_id: 

4395 new_share_net_param = db_utils.create_share_network( 

4396 id=new_share_network_id) 

4397 

4398 share = db_utils.create_share( 

4399 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

4400 share_type_id=fake_type_src['id'], 

4401 share_network_id=new_share_network_id) 

4402 

4403 self.mock_object(utils, 'validate_service_host') 

4404 self.mock_object(db_api, 'share_update') 

4405 self.mock_object(share_types, 'get_share_type', 

4406 mock.Mock(return_value=fake_type_src)) 

4407 

4408 result = self.api.migration_start( 

4409 self.context, share, host, False, True, True, True, True, 

4410 new_share_net_param, new_share_type_param) 

4411 

4412 self.assertEqual(200, result) 

4413 

4414 db_api.share_update.assert_called_once_with( 

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

4416 {'task_state': constants.TASK_STATE_MIGRATION_SUCCESS}) 

4417 

4418 @ddt.data({}, {'replication_type': None}) 

4419 def test_create_share_replica_invalid_share_type(self, attributes): 

4420 share = fakes.fake_share(id='FAKE_SHARE_ID', **attributes) 

4421 mock_request_spec_call = self.mock_object( 

4422 self.api, 'create_share_instance_and_get_request_spec') 

4423 mock_db_update_call = self.mock_object(db_api, 'share_replica_update') 

4424 mock_scheduler_rpcapi_call = self.mock_object( 

4425 self.api.scheduler_rpcapi, 'create_share_replica') 

4426 

4427 self.assertRaises(exception.InvalidShare, 

4428 self.api.create_share_replica, 

4429 self.context, share) 

4430 self.assertFalse(mock_request_spec_call.called) 

4431 self.assertFalse(mock_db_update_call.called) 

4432 self.assertFalse(mock_scheduler_rpcapi_call.called) 

4433 

4434 def test_create_share_replica_busy_share(self): 

4435 share = fakes.fake_share( 

4436 id='FAKE_SHARE_ID', 

4437 task_state='doing_something_real_important', 

4438 is_busy=True, 

4439 replication_type='dr') 

4440 mock_request_spec_call = self.mock_object( 

4441 self.api, 'create_share_instance_and_get_request_spec') 

4442 mock_db_update_call = self.mock_object(db_api, 'share_replica_update') 

4443 mock_scheduler_rpcapi_call = self.mock_object( 

4444 self.api.scheduler_rpcapi, 'create_share_replica') 

4445 

4446 self.assertRaises(exception.ShareBusyException, 

4447 self.api.create_share_replica, 

4448 self.context, share) 

4449 self.assertFalse(mock_request_spec_call.called) 

4450 self.assertFalse(mock_db_update_call.called) 

4451 self.assertFalse(mock_scheduler_rpcapi_call.called) 

4452 

4453 @ddt.data(None, []) 

4454 def test_create_share_replica_no_active_replica(self, active_replicas): 

4455 share = fakes.fake_share( 

4456 id='FAKE_SHARE_ID', replication_type='dr') 

4457 mock_request_spec_call = self.mock_object( 

4458 self.api, 'create_share_instance_and_get_request_spec') 

4459 mock_db_update_call = self.mock_object(db_api, 'share_replica_update') 

4460 mock_scheduler_rpcapi_call = self.mock_object( 

4461 self.api.scheduler_rpcapi, 'create_share_replica') 

4462 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4463 mock.Mock(return_value=active_replicas)) 

4464 

4465 self.assertRaises(exception.ReplicationException, 

4466 self.api.create_share_replica, 

4467 self.context, share) 

4468 self.assertFalse(mock_request_spec_call.called) 

4469 self.assertFalse(mock_db_update_call.called) 

4470 self.assertFalse(mock_scheduler_rpcapi_call.called) 

4471 

4472 @ddt.data(None, 'fake-share-type') 

4473 def test_create_share_replica_type_doesnt_support_AZ(self, st_name): 

4474 share_type = fakes.fake_share_type( 

4475 name=st_name, 

4476 extra_specs={'availability_zones': 'zone 1,zone 3'}) 

4477 share = fakes.fake_share( 

4478 id='FAKE_SHARE_ID', replication_type='dr', 

4479 availability_zone='zone 2') 

4480 share['instance'].update({ 

4481 'share_type': share_type, 

4482 'share_type_id': '359b9851-2bd5-4404-89a9-5cd22bbc5fb9', 

4483 }) 

4484 mock_request_spec_call = self.mock_object( 

4485 self.api, 'create_share_instance_and_get_request_spec') 

4486 mock_db_update_call = self.mock_object(db_api, 'share_replica_update') 

4487 mock_scheduler_rpcapi_call = self.mock_object( 

4488 self.api.scheduler_rpcapi, 'create_share_replica') 

4489 self.mock_object(share_types, 'get_share_type', 

4490 mock.Mock(return_value=share_type)) 

4491 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4492 mock.Mock(return_value=mock.Mock( 

4493 return_value={'host': 'fake_ar_host'}))) 

4494 

4495 self.assertRaises(exception.InvalidShare, 

4496 self.api.create_share_replica, 

4497 self.context, share, availability_zone='zone 2') 

4498 share_types.get_share_type.assert_called_once_with( 

4499 self.context, '359b9851-2bd5-4404-89a9-5cd22bbc5fb9') 

4500 self.assertFalse(mock_request_spec_call.called) 

4501 self.assertFalse(mock_db_update_call.called) 

4502 self.assertFalse(mock_scheduler_rpcapi_call.called) 

4503 

4504 def test_create_share_replica_subnet_not_found(self): 

4505 request_spec = fakes.fake_replica_request_spec() 

4506 replica = request_spec['share_instance_properties'] 

4507 extra_specs = { 

4508 'availability_zones': 'FAKE_AZ,FAKE_AZ2', 

4509 'replication_type': constants.REPLICATION_TYPE_DR 

4510 } 

4511 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

4512 share_type = db_api.share_type_get(self.context, share_type['id']) 

4513 az_name = 'FAKE_AZ' 

4514 share = db_utils.create_share( 

4515 id=replica['share_id'], replication_type='dr') 

4516 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4517 mock.Mock(return_value=mock.Mock( 

4518 return_value={'host': 'fake_ar_host'}))) 

4519 self.mock_object(share_types, 'get_share_type', 

4520 mock.Mock(return_value=share_type)) 

4521 self.mock_object(db_api, 'availability_zone_get') 

4522 self.mock_object( 

4523 db_api, 'share_network_subnets_get_all_by_availability_zone_id', 

4524 mock.Mock(return_value=None)) 

4525 

4526 self.assertRaises(exception.InvalidShare, 

4527 self.api.create_share_replica, 

4528 self.context, 

4529 share, 

4530 availability_zone=az_name, 

4531 share_network_id='fake_id') 

4532 (db_api.share_replicas_get_available_active_replica 

4533 .assert_called_once_with(self.context, share['id'])) 

4534 self.assertTrue(share_types.get_share_type.called) 

4535 db_api.availability_zone_get.assert_called_once_with( 

4536 self.context, az_name) 

4537 self.assertTrue( 

4538 (db_api.share_network_subnets_get_all_by_availability_zone_id. 

4539 called)) 

4540 

4541 def test_create_share_replica_az_not_found(self): 

4542 request_spec = fakes.fake_replica_request_spec() 

4543 replica = request_spec['share_instance_properties'] 

4544 extra_specs = { 

4545 'availability_zones': 'FAKE_AZ,FAKE_AZ2', 

4546 'replication_type': constants.REPLICATION_TYPE_DR 

4547 } 

4548 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

4549 share_type = db_api.share_type_get(self.context, share_type['id']) 

4550 az_name = 'FAKE_AZ' 

4551 share = db_utils.create_share( 

4552 id=replica['share_id'], replication_type='dr') 

4553 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4554 mock.Mock(return_value=mock.Mock( 

4555 return_value={'host': 'fake_ar_host'}))) 

4556 self.mock_object(share_types, 'get_share_type', 

4557 mock.Mock(return_value=share_type)) 

4558 side_effect = exception.AvailabilityZoneNotFound(id=az_name) 

4559 self.mock_object(db_api, 'availability_zone_get', 

4560 mock.Mock(side_effect=side_effect)) 

4561 

4562 self.assertRaises(exception.InvalidInput, 

4563 self.api.create_share_replica, 

4564 self.context, 

4565 share, 

4566 availability_zone=az_name, 

4567 share_network_id='fake_id') 

4568 (db_api.share_replicas_get_available_active_replica 

4569 .assert_called_once_with(self.context, share['id'])) 

4570 self.assertTrue(share_types.get_share_type.called) 

4571 db_api.availability_zone_get.assert_called_once_with( 

4572 self.context, az_name) 

4573 

4574 @ddt.data( 

4575 {'availability_zones': '', 'compatible_azs_name': ['fake_az_1'], 

4576 'compatible_azs_multiple': []}, 

4577 {'availability_zones': 'fake_az_1,fake_az_2', 

4578 'compatible_azs_name': ['fake_az_2'], 'compatible_azs_multiple': []} 

4579 ) 

4580 @ddt.unpack 

4581 def test_create_share_replica_azs_with_subnets(self, availability_zones, 

4582 compatible_azs_name, 

4583 compatible_azs_multiple): 

4584 request_spec = fakes.fake_replica_request_spec() 

4585 replica = request_spec['share_instance_properties'] 

4586 share_network_id = 'fake_share_network_id' 

4587 extra_specs = { 

4588 'availability_zones': availability_zones, 

4589 'replication_type': constants.REPLICATION_TYPE_DR 

4590 } 

4591 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

4592 share_type = db_api.share_type_get(self.context, share_type['id']) 

4593 share = db_utils.create_share( 

4594 id=replica['share_id'], replication_type='dr', 

4595 share_type_id=share_type['id']) 

4596 cast_rules_to_readonly = ( 

4597 share['replication_type'] == constants.REPLICATION_TYPE_READABLE) 

4598 fake_replica = fakes.fake_replica(id=replica['id']) 

4599 fake_request_spec = fakes.fake_replica_request_spec() 

4600 

4601 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4602 mock.Mock(return_value={'host': 'fake_ar_host'})) 

4603 self.mock_object(share_types, 'get_share_type', 

4604 mock.Mock(return_value=share_type)) 

4605 mock_get_all_az_subnet = self.mock_object( 

4606 self.api, '_get_all_availability_zones_with_subnets', 

4607 mock.Mock(return_value=[compatible_azs_name, 

4608 compatible_azs_multiple])) 

4609 

4610 if availability_zones == '': 

4611 expected_azs = compatible_azs_name 

4612 else: 

4613 availability_zones = [ 

4614 t for t in availability_zones.split(',') if availability_zones] 

4615 expected_azs = ( 

4616 [az for az in availability_zones if az in compatible_azs_name]) 

4617 

4618 self.mock_object( 

4619 self.api, 'create_share_instance_and_get_request_spec', 

4620 mock.Mock(return_value=(fake_request_spec, fake_replica))) 

4621 self.mock_object(db_api, 'share_replica_update') 

4622 mock_snapshot_get_all_call = self.mock_object( 

4623 db_api, 'share_snapshot_get_all_for_share', 

4624 mock.Mock(return_value=[])) 

4625 mock_sched_rpcapi_call = self.mock_object( 

4626 self.api.scheduler_rpcapi, 'create_share_replica') 

4627 

4628 self.api.create_share_replica( 

4629 self.context, share, share_network_id=share_network_id) 

4630 

4631 (db_api.share_replicas_get_available_active_replica 

4632 .assert_called_once_with(self.context, share['id'])) 

4633 self.assertTrue(share_types.get_share_type.called) 

4634 mock_get_all_az_subnet.assert_called_once_with( 

4635 self.context, share_network_id 

4636 ) 

4637 (self.api.create_share_instance_and_get_request_spec. 

4638 assert_called_once_with( 

4639 self.context, share, availability_zone=None, 

4640 share_network_id=share_network_id, share_type_id=share_type['id'], 

4641 availability_zones=expected_azs, 

4642 az_request_multiple_subnet_support_map={}, 

4643 cast_rules_to_readonly=cast_rules_to_readonly)) 

4644 db_api.share_replica_update.assert_called_once() 

4645 mock_snapshot_get_all_call.assert_called_once() 

4646 mock_sched_rpcapi_call.assert_called_once() 

4647 

4648 @ddt.data( 

4649 {'availability_zones': '', 'compatible_azs_name': [], 

4650 'compatible_azs_multiple': []}, 

4651 {'availability_zones': 'fake_az_1,fake_az_2', 

4652 'compatible_azs_name': ['fake_az_3'], 'compatible_azs_multiple': []} 

4653 ) 

4654 @ddt.unpack 

4655 def test_create_share_replica_azs_with_subnets_invalid_input( 

4656 self, availability_zones, 

4657 compatible_azs_name, compatible_azs_multiple): 

4658 request_spec = fakes.fake_replica_request_spec() 

4659 replica = request_spec['share_instance_properties'] 

4660 share_network_id = 'fake_share_network_id' 

4661 extra_specs = { 

4662 'availability_zones': availability_zones, 

4663 'replication_type': constants.REPLICATION_TYPE_DR 

4664 } 

4665 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

4666 share_type = db_api.share_type_get(self.context, share_type['id']) 

4667 share = db_utils.create_share( 

4668 id=replica['share_id'], replication_type='dr', 

4669 share_type_id=share_type['id']) 

4670 

4671 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4672 mock.Mock(return_value={'host': 'fake_ar_host'})) 

4673 self.mock_object(share_types, 'get_share_type', 

4674 mock.Mock(return_value=share_type)) 

4675 mock_get_all_az_subnet = self.mock_object( 

4676 self.api, '_get_all_availability_zones_with_subnets', 

4677 mock.Mock(return_value=[compatible_azs_name, 

4678 compatible_azs_multiple])) 

4679 

4680 self.assertRaises( 

4681 exception.InvalidInput, 

4682 self.api.create_share_replica, 

4683 self.context, share, share_network_id=share_network_id) 

4684 

4685 (db_api.share_replicas_get_available_active_replica 

4686 .assert_called_once_with(self.context, share['id'])) 

4687 self.assertTrue(share_types.get_share_type.called) 

4688 mock_get_all_az_subnet.assert_called_once_with( 

4689 self.context, share_network_id 

4690 ) 

4691 

4692 @ddt.data({'has_snapshots': True, 

4693 'az_id': {}, 

4694 'extra_specs': { 

4695 'replication_type': constants.REPLICATION_TYPE_DR, 

4696 }, 

4697 'share_network_id': None}, 

4698 {'has_snapshots': False, 

4699 'az_id': {}, 

4700 'extra_specs': { 

4701 'availability_zones': 'FAKE_AZ,FAKE_AZ2', 

4702 'replication_type': constants.REPLICATION_TYPE_DR, 

4703 }, 

4704 'share_network_id': None}, 

4705 {'has_snapshots': True, 

4706 'az_id': {}, 

4707 'extra_specs': { 

4708 'availability_zones': 'FAKE_AZ,FAKE_AZ2', 

4709 'replication_type': constants.REPLICATION_TYPE_READABLE, 

4710 }, 

4711 'share_network_id': None}, 

4712 {'has_snapshots': False, 

4713 'az_id': {'fake_zone_id': False}, 

4714 'extra_specs': { 

4715 'replication_type': constants.REPLICATION_TYPE_READABLE, 

4716 }, 

4717 'share_network_id': 'fake_sn_id'}) 

4718 @ddt.unpack 

4719 def test_create_share_replica(self, has_snapshots, extra_specs, 

4720 share_network_id, az_id): 

4721 subnets = db_utils.create_share_network_subnet( 

4722 id='fakeid', share_network_id='fake_network_id') 

4723 az = {'id': 'fake_zone_id'} 

4724 request_spec = fakes.fake_replica_request_spec() 

4725 replication_type = extra_specs['replication_type'] 

4726 replica = request_spec['share_instance_properties'] 

4727 share_type = db_utils.create_share_type(extra_specs=extra_specs) 

4728 share_type = db_api.share_type_get(self.context, share_type['id']) 

4729 share = db_utils.create_share( 

4730 id=replica['share_id'], replication_type=replication_type, 

4731 share_type_id=share_type['id']) 

4732 snapshots = ( 

4733 [fakes.fake_snapshot(), fakes.fake_snapshot()] 

4734 if has_snapshots else [] 

4735 ) 

4736 cast_rules_to_readonly = ( 

4737 replication_type == constants.REPLICATION_TYPE_READABLE) 

4738 

4739 fake_replica = fakes.fake_replica(id=replica['id']) 

4740 fake_request_spec = fakes.fake_replica_request_spec() 

4741 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4742 mock.Mock(return_value={'host': 'fake_ar_host'})) 

4743 self.mock_object(share_types, 'get_share_type', 

4744 mock.Mock(return_value=share_type)) 

4745 self.mock_object(db_api, 'availability_zone_get', 

4746 mock.Mock(return_value=az)) 

4747 self.mock_object( 

4748 db_api, 'share_network_subnets_get_all_by_availability_zone_id', 

4749 mock.Mock(return_value=[subnets])) 

4750 self.mock_object( 

4751 share_api.API, 'create_share_instance_and_get_request_spec', 

4752 mock.Mock(return_value=(fake_request_spec, fake_replica))) 

4753 self.mock_object(db_api, 'share_replica_update') 

4754 mock_sched_rpcapi_call = self.mock_object( 

4755 self.api.scheduler_rpcapi, 'create_share_replica') 

4756 mock_snapshot_get_all_call = self.mock_object( 

4757 db_api, 'share_snapshot_get_all_for_share', 

4758 mock.Mock(return_value=snapshots)) 

4759 mock_snapshot_instance_create_call = self.mock_object( 

4760 db_api, 'share_snapshot_instance_create') 

4761 expected_snap_instance_create_call_count = 2 if has_snapshots else 0 

4762 

4763 result = self.api.create_share_replica( 

4764 self.context, share, availability_zone='FAKE_AZ', 

4765 share_network_id=share_network_id) 

4766 

4767 self.assertTrue(mock_sched_rpcapi_call.called) 

4768 self.assertEqual(replica, result) 

4769 share_types.get_share_type.assert_called_once_with( 

4770 self.context, share_type['id']) 

4771 mock_snapshot_get_all_call.assert_called_once_with( 

4772 self.context, fake_replica['share_id']) 

4773 self.assertEqual(expected_snap_instance_create_call_count, 

4774 mock_snapshot_instance_create_call.call_count) 

4775 expected_azs = extra_specs.get('availability_zones', '') 

4776 expected_azs = expected_azs.split(',') if expected_azs else [] 

4777 (share_api.API.create_share_instance_and_get_request_spec. 

4778 assert_called_once_with( 

4779 self.context, share, availability_zone='FAKE_AZ', 

4780 share_network_id=share_network_id, share_type_id=share_type['id'], 

4781 availability_zones=expected_azs, 

4782 az_request_multiple_subnet_support_map=az_id, 

4783 cast_rules_to_readonly=cast_rules_to_readonly)) 

4784 

4785 def test_delete_last_active_replica(self): 

4786 fake_replica = fakes.fake_replica( 

4787 share_id='FAKE_SHARE_ID', 

4788 replica_state=constants.REPLICA_STATE_ACTIVE) 

4789 self.mock_object(db_api, 'share_replicas_get_all_by_share', 

4790 mock.Mock(return_value=[fake_replica])) 

4791 mock_log = self.mock_object(share_api.LOG, 'info') 

4792 

4793 self.assertRaises( 

4794 exception.ReplicationException, self.api.delete_share_replica, 

4795 self.context, fake_replica) 

4796 self.assertFalse(mock_log.called) 

4797 

4798 @ddt.data(True, False) 

4799 def test_delete_share_replica_no_host(self, has_snapshots): 

4800 snapshots = [{'id': 'xyz'}, {'id': 'abc'}, {'id': 'pqr'}] 

4801 snapshots = snapshots if has_snapshots else [] 

4802 replica = fakes.fake_replica('FAKE_ID', host='') 

4803 mock_sched_rpcapi_call = self.mock_object( 

4804 self.share_rpcapi, 'delete_share_replica') 

4805 mock_db_replica_delete_call = self.mock_object( 

4806 db_api, 'share_replica_delete') 

4807 mock_db_update_call = self.mock_object(db_api, 'share_replica_update') 

4808 mock_snapshot_get_call = self.mock_object( 

4809 db_api, 'share_snapshot_instance_get_all_with_filters', 

4810 mock.Mock(return_value=snapshots)) 

4811 mock_snapshot_instance_delete_call = self.mock_object( 

4812 db_api, 'share_snapshot_instance_delete') 

4813 

4814 self.api.delete_share_replica(self.context, replica) 

4815 

4816 self.assertFalse(mock_sched_rpcapi_call.called) 

4817 mock_db_replica_delete_call.assert_called_once_with( 

4818 self.context, replica['id']) 

4819 mock_db_update_call.assert_called_once_with( 

4820 self.context, replica['id'], 

4821 {'status': constants.STATUS_DELETING, 'terminated_at': mock.ANY}) 

4822 mock_snapshot_get_call.assert_called_once_with( 

4823 self.context, {'share_instance_ids': replica['id']}) 

4824 self.assertEqual( 

4825 len(snapshots), mock_snapshot_instance_delete_call.call_count) 

4826 

4827 @ddt.data(True, False) 

4828 def test_delete_share_replica(self, force): 

4829 replica = fakes.fake_replica('FAKE_ID', host='HOSTA@BackendB#PoolC') 

4830 mock_sched_rpcapi_call = self.mock_object( 

4831 self.share_rpcapi, 'delete_share_replica') 

4832 mock_db_update_call = self.mock_object(db_api, 'share_replica_update') 

4833 

4834 self.api.delete_share_replica(self.context, replica, force=force) 

4835 

4836 mock_sched_rpcapi_call.assert_called_once_with( 

4837 self.context, replica, force=force) 

4838 mock_db_update_call.assert_called_once_with( 

4839 self.context, replica['id'], 

4840 {'status': constants.STATUS_DELETING, 

4841 'terminated_at': mock.ANY}) 

4842 

4843 @ddt.data(constants.STATUS_CREATING, constants.STATUS_DELETING, 

4844 constants.STATUS_ERROR, constants.STATUS_EXTENDING, 

4845 constants.STATUS_REPLICATION_CHANGE, constants.STATUS_MANAGING, 

4846 constants.STATUS_ERROR_DELETING) 

4847 def test_promote_share_replica_non_available_status(self, status): 

4848 replica = fakes.fake_replica( 

4849 status=status, replica_state=constants.REPLICA_STATE_IN_SYNC) 

4850 mock_rpcapi_promote_share_replica_call = self.mock_object( 

4851 self.share_rpcapi, 'promote_share_replica') 

4852 

4853 self.assertRaises(exception.ReplicationException, 

4854 self.api.promote_share_replica, 

4855 self.context, 

4856 replica) 

4857 self.assertFalse(mock_rpcapi_promote_share_replica_call.called) 

4858 

4859 @ddt.data(constants.REPLICA_STATE_OUT_OF_SYNC, constants.STATUS_ERROR) 

4860 def test_promote_share_replica_out_of_sync_non_admin(self, replica_state): 

4861 fake_user_context = context.RequestContext( 

4862 user_id=None, project_id=None, is_admin=False, 

4863 read_deleted='no', overwrite=False) 

4864 replica = fakes.fake_replica( 

4865 status=constants.STATUS_AVAILABLE, 

4866 replica_state=replica_state) 

4867 mock_rpcapi_promote_share_replica_call = self.mock_object( 

4868 self.share_rpcapi, 'promote_share_replica') 

4869 

4870 self.assertRaises(exception.AdminRequired, 

4871 self.api.promote_share_replica, 

4872 fake_user_context, 

4873 replica) 

4874 self.assertFalse(mock_rpcapi_promote_share_replica_call.called) 

4875 

4876 @ddt.data(constants.REPLICA_STATE_OUT_OF_SYNC, constants.STATUS_ERROR) 

4877 def test_promote_share_replica_admin_authorized(self, replica_state): 

4878 replica = fakes.fake_replica( 

4879 status=constants.STATUS_AVAILABLE, 

4880 replica_state=replica_state, host='HOSTA@BackendB#PoolC') 

4881 self.mock_object(db_api, 'share_replica_get', 

4882 mock.Mock(return_value=replica)) 

4883 mock_rpcapi_promote_share_replica_call = self.mock_object( 

4884 self.share_rpcapi, 'promote_share_replica') 

4885 mock_db_update_call = self.mock_object(db_api, 'share_replica_update') 

4886 

4887 retval = self.api.promote_share_replica( 

4888 self.context, replica) 

4889 

4890 self.assertEqual(replica, retval) 

4891 mock_db_update_call.assert_called_once_with( 

4892 self.context, replica['id'], 

4893 {'status': constants.STATUS_REPLICATION_CHANGE}) 

4894 mock_rpcapi_promote_share_replica_call.assert_called_once_with( 

4895 self.context, replica, quiesce_wait_time=None) 

4896 

4897 def test_promote_share_replica(self): 

4898 replica = fakes.fake_replica('FAKE_ID', host='HOSTA@BackendB#PoolC') 

4899 self.mock_object(db_api, 'share_replica_get', 

4900 mock.Mock(return_value=replica)) 

4901 self.mock_object(db_api, 'share_replica_update') 

4902 mock_sched_rpcapi_call = self.mock_object( 

4903 self.share_rpcapi, 'promote_share_replica') 

4904 

4905 result = self.api.promote_share_replica(self.context, replica) 

4906 

4907 mock_sched_rpcapi_call.assert_called_once_with( 

4908 self.context, replica, quiesce_wait_time=None) 

4909 self.assertEqual(replica, result) 

4910 

4911 def test_update_share_replica_no_host(self): 

4912 replica = fakes.fake_replica('FAKE_ID') 

4913 replica['host'] = None 

4914 mock_rpcapi_update_share_replica_call = self.mock_object( 

4915 self.share_rpcapi, 'update_share_replica') 

4916 

4917 self.assertRaises(exception.InvalidHost, 

4918 self.api.update_share_replica, 

4919 self.context, 

4920 replica) 

4921 self.assertFalse(mock_rpcapi_update_share_replica_call.called) 

4922 

4923 def test_update_share_replica(self): 

4924 replica = fakes.fake_replica('FAKE_ID', host='HOSTA@BackendB#PoolC') 

4925 mock_rpcapi_update_share_replica_call = self.mock_object( 

4926 self.share_rpcapi, 'update_share_replica') 

4927 

4928 retval = self.api.update_share_replica(self.context, replica) 

4929 

4930 self.assertTrue(mock_rpcapi_update_share_replica_call.called) 

4931 self.assertIsNone(retval) 

4932 

4933 @ddt.data({'overs': {'replica_gigabytes': 'fake'}, 

4934 'expected_exception': 

4935 exception.ShareReplicaSizeExceedsAvailableQuota}, 

4936 {'overs': {'share_replicas': 'fake'}, 

4937 'expected_exception': exception.ShareReplicasLimitExceeded}) 

4938 @ddt.unpack 

4939 def test_create_share_replica_over_quota(self, overs, expected_exception): 

4940 request_spec = fakes.fake_replica_request_spec() 

4941 replica = request_spec['share_instance_properties'] 

4942 share = db_utils.create_share(replication_type='dr', 

4943 id=replica['share_id']) 

4944 share_type = db_utils.create_share_type() 

4945 share_type = db_api.share_type_get(self.context, share_type['id']) 

4946 usages = {'replica_gigabytes': {'reserved': 5, 'in_use': 5}, 

4947 'share_replicas': {'reserved': 5, 'in_use': 5}} 

4948 quotas = {'share_replicas': 5, 'replica_gigabytes': 5} 

4949 exc = exception.OverQuota(overs=overs, usages=usages, quotas=quotas) 

4950 

4951 self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc)) 

4952 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4953 mock.Mock(return_value={'host': 'fake_ar_host'})) 

4954 self.mock_object(share_types, 'get_share_type', 

4955 mock.Mock(return_value=share_type)) 

4956 

4957 self.assertRaises( 

4958 expected_exception, 

4959 self.api.create_share_replica, 

4960 self.context, 

4961 share 

4962 ) 

4963 quota.QUOTAS.reserve.assert_called_once_with( 

4964 self.context, share_type_id=share_type['id'], 

4965 share_replicas=1, replica_gigabytes=share['size']) 

4966 (db_api.share_replicas_get_available_active_replica 

4967 .assert_called_once_with(self.context, share['id'])) 

4968 share_types.get_share_type.assert_called_once_with( 

4969 self.context, share['instance']['share_type_id']) 

4970 

4971 def test_create_share_replica_error_on_quota_commit(self): 

4972 request_spec = fakes.fake_replica_request_spec() 

4973 replica = request_spec['share_instance_properties'] 

4974 share_type = db_utils.create_share_type() 

4975 fake_replica = fakes.fake_replica(id=replica['id']) 

4976 share = db_utils.create_share(replication_type='dr', 

4977 id=fake_replica['share_id'], 

4978 share_type_id=share_type['id']) 

4979 share_network_id = None 

4980 share_type = db_api.share_type_get(self.context, share_type['id']) 

4981 expected_azs = share_type['extra_specs'].get('availability_zones', '') 

4982 expected_azs = expected_azs.split(',') if expected_azs else [] 

4983 

4984 reservation = 'fake' 

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

4986 mock.Mock(return_value=reservation)) 

4987 self.mock_object(quota.QUOTAS, 'commit', 

4988 mock.Mock(side_effect=exception.QuotaError('fake'))) 

4989 self.mock_object(db_api, 'share_replica_delete') 

4990 self.mock_object(quota.QUOTAS, 'rollback') 

4991 self.mock_object(db_api, 'share_replicas_get_available_active_replica', 

4992 mock.Mock(return_value={'host': 'fake_ar_host'})) 

4993 self.mock_object(share_types, 'get_share_type', 

4994 mock.Mock(return_value=share_type)) 

4995 self.mock_object( 

4996 share_api.API, 'create_share_instance_and_get_request_spec', 

4997 mock.Mock(return_value=(request_spec, fake_replica))) 

4998 

4999 self.assertRaises( 

5000 exception.QuotaError, 

5001 self.api.create_share_replica, 

5002 self.context, 

5003 share 

5004 ) 

5005 

5006 db_api.share_replica_delete.assert_called_once_with( 

5007 self.context, replica['id'], need_to_update_usages=False) 

5008 quota.QUOTAS.rollback.assert_called_once_with( 

5009 self.context, reservation, 

5010 share_type_id=share['instance']['share_type_id']) 

5011 (db_api.share_replicas_get_available_active_replica. 

5012 assert_called_once_with(self.context, share['id'])) 

5013 share_types.get_share_type.assert_called_once_with( 

5014 self.context, share['instance']['share_type_id']) 

5015 (share_api.API.create_share_instance_and_get_request_spec. 

5016 assert_called_once_with(self.context, share, availability_zone=None, 

5017 share_network_id=share_network_id, 

5018 share_type_id=share_type['id'], 

5019 availability_zones=expected_azs, 

5020 az_request_multiple_subnet_support_map={}, 

5021 cast_rules_to_readonly=False)) 

5022 

5023 def test_migration_complete(self): 

5024 

5025 instance1 = db_utils.create_share_instance( 

5026 share_id='fake_id', status=constants.STATUS_MIGRATING) 

5027 instance2 = db_utils.create_share_instance( 

5028 share_id='fake_id', status=constants.STATUS_MIGRATING_TO) 

5029 share = db_utils.create_share( 

5030 id='fake_id', 

5031 task_state=constants.TASK_STATE_DATA_COPYING_COMPLETED, 

5032 instances=[instance1, instance2]) 

5033 

5034 self.mock_object(db_api, 'share_instance_get', 

5035 mock.Mock(return_value=instance1)) 

5036 self.mock_object(self.api.share_rpcapi, 'migration_complete') 

5037 

5038 self.api.migration_complete(self.context, share) 

5039 

5040 self.api.share_rpcapi.migration_complete.assert_called_once_with( 

5041 self.context, instance1, instance2['id']) 

5042 

5043 @ddt.data(constants.TASK_STATE_DATA_COPYING_STARTING, 

5044 constants.TASK_STATE_MIGRATION_SUCCESS, 

5045 constants.TASK_STATE_DATA_COPYING_IN_PROGRESS, 

5046 constants.TASK_STATE_MIGRATION_ERROR, 

5047 constants.TASK_STATE_MIGRATION_CANCELLED, 

5048 None) 

5049 def test_migration_complete_task_state_invalid(self, task_state): 

5050 

5051 share = db_utils.create_share( 

5052 id='fake_id', 

5053 task_state=task_state) 

5054 

5055 self.assertRaises(exception.InvalidShare, self.api.migration_complete, 

5056 self.context, share) 

5057 

5058 def test_migration_complete_status_invalid(self): 

5059 

5060 instance1 = db_utils.create_share_instance( 

5061 share_id='fake_id', status=constants.STATUS_ERROR) 

5062 instance2 = db_utils.create_share_instance( 

5063 share_id='fake_id', status=constants.STATUS_ERROR) 

5064 share = db_utils.create_share( 

5065 id='fake_id', 

5066 task_state=constants.TASK_STATE_DATA_COPYING_COMPLETED, 

5067 instances=[instance1, instance2]) 

5068 

5069 self.assertRaises(exception.ShareMigrationFailed, 

5070 self.api.migration_complete, self.context, 

5071 share) 

5072 

5073 @ddt.data(None, Exception('fake')) 

5074 def test_migration_cancel(self, exc): 

5075 

5076 share = db_utils.create_share( 

5077 id='fake_id', 

5078 task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS) 

5079 services = ['fake_service'] 

5080 

5081 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

5082 self.mock_object(db_api, 'service_get_all_by_topic', 

5083 mock.Mock(return_value=services)) 

5084 self.mock_object(data_rpc.DataAPI, 'data_copy_cancel', 

5085 mock.Mock(side_effect=[exc])) 

5086 

5087 if exc: 

5088 self.assertRaises( 

5089 exception.ShareMigrationError, self.api.migration_cancel, 

5090 self.context, share) 

5091 else: 

5092 self.api.migration_cancel(self.context, share) 

5093 

5094 data_rpc.DataAPI.data_copy_cancel.assert_called_once_with( 

5095 self.context, share['id']) 

5096 db_api.service_get_all_by_topic.assert_called_once_with( 

5097 self.context, 'manila-data') 

5098 

5099 def test_migration_cancel_service_down(self): 

5100 service = 'fake_service' 

5101 instance1 = db_utils.create_share_instance( 

5102 share_id='fake_id', status=constants.STATUS_MIGRATING) 

5103 instance2 = db_utils.create_share_instance( 

5104 share_id='fake_id', status=constants.STATUS_MIGRATING_TO) 

5105 share = db_utils.create_share( 

5106 id='fake_id', 

5107 task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS, 

5108 instances=[instance1, instance2]) 

5109 

5110 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False)) 

5111 self.mock_object(db_api, 'share_instance_get', 

5112 mock.Mock(return_value=instance1)) 

5113 self.mock_object(db_api, 'service_get_all_by_topic', 

5114 mock.Mock(return_value=service)) 

5115 

5116 self.assertRaises(exception.InvalidShare, 

5117 self.api.migration_cancel, self.context, share) 

5118 

5119 def test_migration_cancel_driver(self): 

5120 

5121 service = 'fake_service' 

5122 instance1 = db_utils.create_share_instance( 

5123 share_id='fake_id', 

5124 status=constants.STATUS_MIGRATING, 

5125 host='some_host') 

5126 instance2 = db_utils.create_share_instance( 

5127 share_id='fake_id', 

5128 status=constants.STATUS_MIGRATING_TO) 

5129 share = db_utils.create_share( 

5130 id='fake_id', 

5131 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

5132 instances=[instance1, instance2]) 

5133 

5134 self.mock_object(db_api, 'share_instance_get', 

5135 mock.Mock(return_value=instance1)) 

5136 self.mock_object(self.api.share_rpcapi, 'migration_cancel') 

5137 self.mock_object(db_api, 'service_get_by_args', 

5138 mock.Mock(return_value=service)) 

5139 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

5140 

5141 self.api.migration_cancel(self.context, share) 

5142 

5143 self.api.share_rpcapi.migration_cancel.assert_called_once_with( 

5144 self.context, instance1, instance2['id']) 

5145 db_api.service_get_by_args.assert_called_once_with( 

5146 self.context, instance1['host'], 'manila-share') 

5147 

5148 @ddt.data(constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

5149 constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE, 

5150 constants.TASK_STATE_DATA_COPYING_COMPLETED) 

5151 def test_migration_cancel_driver_service_down(self, task_state): 

5152 

5153 service = 'fake_service' 

5154 instance1 = db_utils.create_share_instance( 

5155 share_id='fake_id', 

5156 status=constants.STATUS_MIGRATING, 

5157 host='some_host') 

5158 instance2 = db_utils.create_share_instance( 

5159 share_id='fake_id', 

5160 status=constants.STATUS_MIGRATING_TO) 

5161 share = db_utils.create_share( 

5162 id='fake_id', 

5163 task_state=task_state, 

5164 instances=[instance1, instance2]) 

5165 

5166 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False)) 

5167 self.mock_object(db_api, 'share_instance_get', 

5168 mock.Mock(return_value=instance1)) 

5169 self.mock_object(db_api, 'service_get_by_args', 

5170 mock.Mock(return_value=service)) 

5171 

5172 self.assertRaises(exception.InvalidShare, 

5173 self.api.migration_cancel, self.context, share) 

5174 

5175 @ddt.data(constants.TASK_STATE_DATA_COPYING_STARTING, 

5176 constants.TASK_STATE_MIGRATION_SUCCESS, 

5177 constants.TASK_STATE_MIGRATION_ERROR, 

5178 constants.TASK_STATE_MIGRATION_CANCELLED, 

5179 None) 

5180 def test_migration_cancel_task_state_invalid(self, task_state): 

5181 

5182 share = db_utils.create_share( 

5183 id='fake_id', 

5184 task_state=task_state) 

5185 

5186 self.assertRaises(exception.InvalidShare, self.api.migration_cancel, 

5187 self.context, share) 

5188 

5189 @ddt.data({'total_progress': 50}, Exception('fake')) 

5190 def test_migration_get_progress(self, expected): 

5191 

5192 share = db_utils.create_share( 

5193 id='fake_id', 

5194 task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS) 

5195 services = ['fake_service'] 

5196 

5197 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

5198 self.mock_object(db_api, 'service_get_all_by_topic', 

5199 mock.Mock(return_value=services)) 

5200 self.mock_object(data_rpc.DataAPI, 'data_copy_get_progress', 

5201 mock.Mock(side_effect=[expected])) 

5202 

5203 if not isinstance(expected, Exception): 

5204 result = self.api.migration_get_progress(self.context, share) 

5205 self.assertEqual(expected, result) 

5206 else: 

5207 self.assertRaises( 

5208 exception.ShareMigrationError, self.api.migration_get_progress, 

5209 self.context, share) 

5210 

5211 data_rpc.DataAPI.data_copy_get_progress.assert_called_once_with( 

5212 self.context, share['id']) 

5213 db_api.service_get_all_by_topic.assert_called_once_with( 

5214 self.context, 'manila-data') 

5215 

5216 def test_migration_get_progress_service_down(self): 

5217 instance1 = db_utils.create_share_instance( 

5218 share_id='fake_id', status=constants.STATUS_MIGRATING) 

5219 instance2 = db_utils.create_share_instance( 

5220 share_id='fake_id', status=constants.STATUS_MIGRATING_TO) 

5221 share = db_utils.create_share( 

5222 id='fake_id', 

5223 task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS, 

5224 instances=[instance1, instance2]) 

5225 services = ['fake_service'] 

5226 

5227 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False)) 

5228 self.mock_object(db_api, 'service_get_all_by_topic', 

5229 mock.Mock(return_value=services)) 

5230 self.mock_object(db_api, 'share_instance_get', 

5231 mock.Mock(return_value=instance1)) 

5232 

5233 self.assertRaises(exception.InvalidShare, 

5234 self.api.migration_get_progress, self.context, share) 

5235 

5236 def test_migration_get_progress_driver(self): 

5237 

5238 expected = {'total_progress': 50} 

5239 instance1 = db_utils.create_share_instance( 

5240 share_id='fake_id', 

5241 status=constants.STATUS_MIGRATING, 

5242 host='some_host') 

5243 instance2 = db_utils.create_share_instance( 

5244 share_id='fake_id', 

5245 status=constants.STATUS_MIGRATING_TO) 

5246 share = db_utils.create_share( 

5247 id='fake_id', 

5248 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

5249 instances=[instance1, instance2]) 

5250 service = 'fake_service' 

5251 

5252 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

5253 self.mock_object(db_api, 'service_get_by_args', 

5254 mock.Mock(return_value=service)) 

5255 self.mock_object(db_api, 'share_instance_get', 

5256 mock.Mock(return_value=instance1)) 

5257 self.mock_object(self.api.share_rpcapi, 'migration_get_progress', 

5258 mock.Mock(return_value=expected)) 

5259 

5260 result = self.api.migration_get_progress(self.context, share) 

5261 

5262 self.assertEqual(expected, result) 

5263 

5264 self.api.share_rpcapi.migration_get_progress.assert_called_once_with( 

5265 self.context, instance1, instance2['id']) 

5266 db_api.service_get_by_args.assert_called_once_with( 

5267 self.context, instance1['host'], 'manila-share') 

5268 

5269 def test_migration_get_progress_driver_error(self): 

5270 

5271 instance1 = db_utils.create_share_instance( 

5272 share_id='fake_id', 

5273 status=constants.STATUS_MIGRATING, 

5274 host='some_host') 

5275 instance2 = db_utils.create_share_instance( 

5276 share_id='fake_id', 

5277 status=constants.STATUS_MIGRATING_TO) 

5278 share = db_utils.create_share( 

5279 id='fake_id', 

5280 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

5281 instances=[instance1, instance2]) 

5282 service = 'fake_service' 

5283 

5284 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

5285 self.mock_object(db_api, 'service_get_by_args', 

5286 mock.Mock(return_value=service)) 

5287 self.mock_object(db_api, 'share_instance_get', 

5288 mock.Mock(return_value=instance1)) 

5289 self.mock_object(self.api.share_rpcapi, 'migration_get_progress', 

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

5291 

5292 self.assertRaises(exception.ShareMigrationError, 

5293 self.api.migration_get_progress, self.context, share) 

5294 

5295 self.api.share_rpcapi.migration_get_progress.assert_called_once_with( 

5296 self.context, instance1, instance2['id']) 

5297 

5298 def test_migration_get_progress_driver_service_down(self): 

5299 service = 'fake_service' 

5300 instance1 = db_utils.create_share_instance( 

5301 share_id='fake_id', 

5302 status=constants.STATUS_MIGRATING, 

5303 host='some_host') 

5304 instance2 = db_utils.create_share_instance( 

5305 share_id='fake_id', 

5306 status=constants.STATUS_MIGRATING_TO) 

5307 share = db_utils.create_share( 

5308 id='fake_id', 

5309 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

5310 instances=[instance1, instance2]) 

5311 

5312 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False)) 

5313 self.mock_object(db_api, 'share_instance_get', 

5314 mock.Mock(return_value=instance1)) 

5315 self.mock_object(db_api, 'service_get_by_args', 

5316 mock.Mock(return_value=service)) 

5317 

5318 self.assertRaises(exception.InvalidShare, 

5319 self.api.migration_get_progress, self.context, share) 

5320 

5321 @ddt.data(constants.TASK_STATE_MIGRATION_STARTING, 

5322 constants.TASK_STATE_MIGRATION_DRIVER_STARTING, 

5323 constants.TASK_STATE_DATA_COPYING_STARTING, 

5324 constants.TASK_STATE_MIGRATION_IN_PROGRESS) 

5325 def test_migration_get_progress_task_state_progress_0(self, task_state): 

5326 

5327 share = db_utils.create_share( 

5328 id='fake_id', 

5329 task_state=task_state) 

5330 expected = {'total_progress': 0} 

5331 

5332 result = self.api.migration_get_progress(self.context, share) 

5333 

5334 self.assertEqual(expected, result) 

5335 

5336 @ddt.data(constants.TASK_STATE_MIGRATION_SUCCESS, 

5337 constants.TASK_STATE_DATA_COPYING_ERROR, 

5338 constants.TASK_STATE_MIGRATION_CANCELLED, 

5339 constants.TASK_STATE_MIGRATION_COMPLETING, 

5340 constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE, 

5341 constants.TASK_STATE_DATA_COPYING_COMPLETED, 

5342 constants.TASK_STATE_DATA_COPYING_COMPLETING, 

5343 constants.TASK_STATE_DATA_COPYING_CANCELLED, 

5344 constants.TASK_STATE_MIGRATION_ERROR) 

5345 def test_migration_get_progress_task_state_progress_100(self, task_state): 

5346 

5347 share = db_utils.create_share( 

5348 id='fake_id', 

5349 task_state=task_state) 

5350 expected = {'total_progress': 100} 

5351 

5352 result = self.api.migration_get_progress(self.context, share) 

5353 

5354 self.assertEqual(expected, result) 

5355 

5356 def test_migration_get_progress_task_state_None(self): 

5357 

5358 share = db_utils.create_share(id='fake_id', task_state=None) 

5359 

5360 self.assertRaises(exception.InvalidShare, 

5361 self.api.migration_get_progress, self.context, share) 

5362 

5363 @ddt.data(None, {'invalid_progress': None}, {}) 

5364 def test_migration_get_progress_invalid(self, progress): 

5365 

5366 instance1 = db_utils.create_share_instance( 

5367 share_id='fake_id', 

5368 status=constants.STATUS_MIGRATING, 

5369 host='some_host') 

5370 instance2 = db_utils.create_share_instance( 

5371 share_id='fake_id', 

5372 status=constants.STATUS_MIGRATING_TO) 

5373 share = db_utils.create_share( 

5374 id='fake_id', 

5375 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

5376 instances=[instance1, instance2]) 

5377 service = 'fake_service' 

5378 

5379 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

5380 self.mock_object(db_api, 'service_get_by_args', 

5381 mock.Mock(return_value=service)) 

5382 self.mock_object(db_api, 'share_instance_get', 

5383 mock.Mock(return_value=instance1)) 

5384 

5385 self.mock_object(self.api.share_rpcapi, 'migration_get_progress', 

5386 mock.Mock(return_value=progress)) 

5387 

5388 self.assertRaises(exception.InvalidShare, 

5389 self.api.migration_get_progress, self.context, share) 

5390 

5391 self.api.share_rpcapi.migration_get_progress.assert_called_once_with( 

5392 self.context, instance1, instance2['id']) 

5393 

5394 @ddt.data(True, False) 

5395 def test__migration_initial_checks(self, create_share_network): 

5396 type_data = { 

5397 'extra_specs': { 

5398 'availability_zones': 'fake_az1,fake_az2' 

5399 } 

5400 } 

5401 fake_server_host = 'fake@backend' 

5402 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5403 share_type = db_utils.create_share_type(**type_data) 

5404 share_type = db_api.share_type_get(self.context, share_type['id']) 

5405 fake_share = db_utils.create_share( 

5406 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

5407 share_type_id=share_type['id']) 

5408 fake_az = { 

5409 'id': 'fake_az_id', 

5410 'name': 'fake_az1' 

5411 } 

5412 fake_share_network = ( 

5413 db_utils.create_share_network() if create_share_network else None) 

5414 expected_network_change = create_share_network is True 

5415 

5416 fake_share_network_id = ( 

5417 fake_share_network['id'] 

5418 if create_share_network else fake_share['share_network_id']) 

5419 fake_subnet = db_utils.create_share_network_subnet( 

5420 availability_zone_id=fake_az['id']) 

5421 

5422 fake_host = 'test@fake' 

5423 service = {'availability_zone_id': fake_az['id'], 

5424 'availability_zone': {'name': fake_az['name']}} 

5425 

5426 mock_shares_get_all = self.mock_object( 

5427 db_api, 'share_get_all_by_share_server', 

5428 mock.Mock(return_value=[fake_share])) 

5429 mock_shares_in_recycle_bin_get_all = self.mock_object( 

5430 db_api, 'share_get_all_soft_deleted', 

5431 mock.Mock(return_value=[])) 

5432 mock_get_type = self.mock_object( 

5433 share_types, 'get_share_type', mock.Mock(return_value=share_type)) 

5434 mock_validate_service = self.mock_object( 

5435 utils, 'validate_service_host') 

5436 mock_service_get = self.mock_object( 

5437 db_api, 'service_get_by_args', mock.Mock(return_value=service)) 

5438 mock_az_get = self.mock_object( 

5439 db_api, 'availability_zone_get', mock.Mock(return_value=fake_az)) 

5440 mock_get_subnet = self.mock_object( 

5441 db_api, 'share_network_subnets_get_all_by_availability_zone_id', 

5442 mock.Mock(return_value=[fake_subnet])) 

5443 

5444 exp_shares, exp_types, exp_service, exp_network_id, net_change = ( 

5445 self.api._migration_initial_checks( 

5446 self.context, fake_share_server, fake_host, 

5447 fake_share_network)) 

5448 

5449 self.assertEqual(exp_shares, [fake_share]) 

5450 self.assertEqual(exp_types, [share_type]) 

5451 self.assertEqual(exp_service, service) 

5452 self.assertEqual(exp_network_id, fake_share_network_id) 

5453 self.assertIs(expected_network_change, net_change) 

5454 mock_shares_get_all.assert_has_calls([ 

5455 mock.call(self.context, fake_share_server['id']), 

5456 mock.call(self.context, fake_share_server['id'])]) 

5457 mock_shares_in_recycle_bin_get_all.assert_has_calls([ 

5458 mock.call(self.context, fake_share_server['id'])]) 

5459 mock_get_type.assert_called_once_with(self.context, share_type['id']) 

5460 mock_validate_service.assert_called_once_with(self.context, fake_host) 

5461 mock_service_get.assert_called_once_with( 

5462 self.context, fake_host, 'manila-share') 

5463 mock_get_subnet.assert_called_once_with( 

5464 self.context, fake_share_network_id, fake_az['id']) 

5465 mock_az_get.assert_called_once_with( 

5466 self.context, service['availability_zone']['name'] 

5467 ) 

5468 

5469 def test_share_server_migration_get_destination(self): 

5470 fake_source_server_id = 'fake_source_id' 

5471 server_data = { 

5472 'id': 'fake', 

5473 'source_share_server_id': fake_source_server_id, 

5474 'status': constants.STATUS_SERVER_MIGRATING_TO, 

5475 } 

5476 server = db_utils.create_share_server(**server_data) 

5477 mock_get_all = self.mock_object( 

5478 db_api, 'share_server_get_all_with_filters', 

5479 mock.Mock(return_value=[server])) 

5480 filters = { 

5481 'status': constants.STATUS_SERVER_MIGRATING_TO, 

5482 'source_share_server_id': fake_source_server_id, 

5483 } 

5484 

5485 filtered_server = self.api.share_server_migration_get_destination( 

5486 self.context, fake_source_server_id, 

5487 status=constants.STATUS_SERVER_MIGRATING_TO 

5488 ) 

5489 self.assertEqual(filtered_server['id'], server['id']) 

5490 mock_get_all.assert_called_once_with(self.context, filters=filters) 

5491 

5492 def test_share_server_migration_get_destination_no_share_server( 

5493 self): 

5494 

5495 fake_source_server_id = 'fake_source_id' 

5496 server_data = { 

5497 'id': 'fake', 

5498 'source_share_server_id': fake_source_server_id, 

5499 'status': constants.STATUS_SERVER_MIGRATING_TO, 

5500 } 

5501 db_utils.create_share_server(**server_data) 

5502 mock_get_all = self.mock_object( 

5503 db_api, 'share_server_get_all_with_filters', 

5504 mock.Mock(return_value=[])) 

5505 filters = { 

5506 'status': constants.STATUS_SERVER_MIGRATING_TO, 

5507 'source_share_server_id': fake_source_server_id, 

5508 } 

5509 

5510 self.assertRaises( 

5511 exception.InvalidShareServer, 

5512 self.api.share_server_migration_get_destination, 

5513 self.context, fake_source_server_id, 

5514 status=constants.STATUS_SERVER_MIGRATING_TO 

5515 ) 

5516 mock_get_all.assert_called_once_with(self.context, filters=filters) 

5517 

5518 def test_share_server_migration_get_destination_multiple_servers(self): 

5519 fake_source_server_id = 'fake_source_id' 

5520 server_data = { 

5521 'id': 'fake', 

5522 'source_share_server_id': fake_source_server_id, 

5523 'status': constants.STATUS_SERVER_MIGRATING_TO, 

5524 } 

5525 server_1 = db_utils.create_share_server(**server_data) 

5526 server_data['id'] = 'fake_id_2' 

5527 server_2 = db_utils.create_share_server(**server_data) 

5528 mock_get_all = self.mock_object( 

5529 db_api, 'share_server_get_all_with_filters', 

5530 mock.Mock(return_value=[server_1, server_2])) 

5531 filters = { 

5532 'status': constants.STATUS_SERVER_MIGRATING_TO, 

5533 'source_share_server_id': fake_source_server_id, 

5534 } 

5535 

5536 self.assertRaises( 

5537 exception.InvalidShareServer, 

5538 self.api.share_server_migration_get_destination, 

5539 self.context, fake_source_server_id, 

5540 status=constants.STATUS_SERVER_MIGRATING_TO 

5541 ) 

5542 mock_get_all.assert_called_once_with(self.context, filters=filters) 

5543 

5544 def test__migration_initial_checks_no_shares(self): 

5545 fake_share_server = fakes.fake_share_server_get() 

5546 fake_share_network = {} 

5547 fake_host = 'test@fake' 

5548 mock_shares_get_all = self.mock_object( 

5549 db_api, 'share_get_all_by_share_server', 

5550 mock.Mock(return_value=[])) 

5551 

5552 self.assertRaises( 

5553 exception.InvalidShareServer, 

5554 self.api._migration_initial_checks, 

5555 self.context, fake_share_server, fake_host, fake_share_network, 

5556 ) 

5557 mock_shares_get_all.assert_called_once_with( 

5558 self.context, fake_share_server['id']) 

5559 

5560 def test__migration_initial_checks_server_not_active(self): 

5561 fake_share_server = fakes.fake_share_server_get() 

5562 fake_share_server['status'] = 'error' 

5563 fake_share = fakes.fake_share() 

5564 fake_share_network = {} 

5565 fake_host = 'test@fake' 

5566 

5567 mock_shares_get_all = self.mock_object( 

5568 db_api, 'share_get_all_by_share_server', 

5569 mock.Mock(return_value=[fake_share])) 

5570 

5571 self.assertRaises( 

5572 exception.InvalidShareServer, 

5573 self.api._migration_initial_checks, 

5574 self.context, fake_share_server, fake_host, fake_share_network, 

5575 ) 

5576 mock_shares_get_all.assert_called_once_with( 

5577 self.context, fake_share_server['id']) 

5578 

5579 def test__migration_initial_checks_share_group_related_to_server(self): 

5580 fake_share_server = db_utils.create_share_server() 

5581 fake_share = db_utils.create_share() 

5582 fake_share_group = db_utils.create_share_group() 

5583 fake_share_network = {} 

5584 fake_host = 'test@fake' 

5585 

5586 mock_shares_get_all = self.mock_object( 

5587 db_api, 'share_get_all_by_share_server', 

5588 mock.Mock(return_value=[fake_share])) 

5589 mock_get_groups = self.mock_object( 

5590 db_api, 'share_group_get_all_by_share_server', 

5591 mock.Mock(return_value=[fake_share_group])) 

5592 

5593 self.assertRaises( 

5594 exception.InvalidShareServer, 

5595 self.api._migration_initial_checks, 

5596 self.context, fake_share_server, fake_host, fake_share_network, 

5597 ) 

5598 mock_shares_get_all.assert_called_once_with( 

5599 self.context, fake_share_server['id']) 

5600 mock_get_groups.assert_called_once_with(self.context, 

5601 fake_share_server['id']) 

5602 

5603 def _setup_mocks_for_initial_checks(self, fake_share, share_type, service, 

5604 fake_az, fake_subnet): 

5605 self.mock_object( 

5606 db_api, 'share_get_all_by_share_server', 

5607 mock.Mock(return_value=[fake_share])) 

5608 self.mock_object( 

5609 db_api, 'share_group_get_all_by_share_server', 

5610 mock.Mock(return_value=[])) 

5611 self.mock_object( 

5612 share_types, 'get_share_type', mock.Mock(return_value=share_type)) 

5613 self.mock_object( 

5614 utils, 'validate_service_host') 

5615 self.mock_object( 

5616 db_api, 'service_get_by_args', mock.Mock(return_value=service)) 

5617 self.mock_object( 

5618 db_api, 'availability_zone_get', mock.Mock(return_value=fake_az)) 

5619 self.mock_object( 

5620 db_api, 'share_network_subnets_get_all_by_availability_zone_id', 

5621 mock.Mock(return_value=fake_subnet)) 

5622 

5623 def test__migration_initial_checks_share_not_available(self): 

5624 fake_share_server = fakes.fake_share_server_get() 

5625 fake_share_server['host'] = 'fake@backend' 

5626 type_data = { 

5627 'extra_specs': { 

5628 'availability_zones': 'fake_az1,fake_az2' 

5629 } 

5630 } 

5631 fake_server_host = 'fake@backend' 

5632 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5633 share_type = db_utils.create_share_type(**type_data) 

5634 share_type = db_api.share_type_get(self.context, share_type['id']) 

5635 fake_share = db_utils.create_share( 

5636 host='fake@backend#pool', status=constants.STATUS_ERROR, 

5637 share_type_id=share_type['id']) 

5638 fake_az = { 

5639 'id': 'fake_az_id', 

5640 'name': 'fake_az1' 

5641 } 

5642 fake_share_network = None 

5643 fake_share_network_id = fake_share['share_network_id'] 

5644 fake_subnet = db_utils.create_share_network_subnet( 

5645 availability_zone_id=fake_az['id']) 

5646 fake_host = 'test@fake' 

5647 service = {'availability_zone_id': fake_az['id'], 

5648 'availability_zone': {'name': fake_az['name']}} 

5649 self._setup_mocks_for_initial_checks(fake_share, share_type, service, 

5650 fake_az, fake_subnet) 

5651 

5652 self.assertRaises( 

5653 exception.InvalidShareServer, 

5654 self.api._migration_initial_checks, 

5655 self.context, fake_share_server, fake_host, fake_share_network, 

5656 ) 

5657 db_api.share_get_all_by_share_server.assert_has_calls([ 

5658 mock.call(self.context, fake_share_server['id']), 

5659 mock.call(self.context, fake_share_server['id'])]) 

5660 share_types.get_share_type.assert_called_once_with( 

5661 self.context, share_type['id']) 

5662 utils.validate_service_host.assert_called_once_with( 

5663 self.context, fake_host) 

5664 db_api.service_get_by_args.assert_called_once_with( 

5665 self.context, fake_host, 'manila-share') 

5666 db_api.availability_zone_get.assert_called_once_with( 

5667 self.context, service['availability_zone']['name'] 

5668 ) 

5669 (db_api.share_network_subnets_get_all_by_availability_zone_id. 

5670 assert_called_once_with( 

5671 self.context, fake_share_network_id, fake_az['id'])) 

5672 db_api.share_group_get_all_by_share_server.assert_called_once_with( 

5673 self.context, fake_share_server['id']) 

5674 

5675 def test__migration_initial_checks_share_with_replicas(self): 

5676 fake_share_server = fakes.fake_share_server_get() 

5677 fake_share_server['host'] = 'fake@backend' 

5678 type_data = { 

5679 'extra_specs': { 

5680 'availability_zones': 'fake_az1,fake_az2' 

5681 } 

5682 } 

5683 fake_server_host = 'fake@backend' 

5684 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5685 share_type = db_utils.create_share_type(**type_data) 

5686 share_type = db_api.share_type_get(self.context, share_type['id']) 

5687 fake_share = db_utils.create_share( 

5688 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

5689 replication_type='dr', share_type_id=share_type['id']) 

5690 for i in range(1, 4): 

5691 db_utils.create_share_replica( 

5692 share_id=fake_share['id'], replica_state='in_sync') 

5693 fake_share = db_api.share_get(self.context, fake_share['id']) 

5694 fake_az = { 

5695 'id': 'fake_az_id', 

5696 'name': 'fake_az1' 

5697 } 

5698 fake_share_network = None 

5699 fake_share_network_id = fake_share['share_network_id'] 

5700 fake_subnet = db_utils.create_share_network_subnet( 

5701 availability_zone_id=fake_az['id']) 

5702 fake_host = 'test@fake' 

5703 service = {'availability_zone_id': fake_az['id'], 

5704 'availability_zone': {'name': fake_az['name']}} 

5705 self._setup_mocks_for_initial_checks(fake_share, share_type, service, 

5706 fake_az, fake_subnet) 

5707 

5708 self.assertRaises( 

5709 exception.InvalidShareServer, 

5710 self.api._migration_initial_checks, 

5711 self.context, fake_share_server, fake_host, fake_share_network, 

5712 ) 

5713 db_api.share_get_all_by_share_server.assert_has_calls([ 

5714 mock.call(self.context, fake_share_server['id']), 

5715 mock.call(self.context, fake_share_server['id'])]) 

5716 share_types.get_share_type.assert_called_once_with( 

5717 self.context, share_type['id']) 

5718 utils.validate_service_host.assert_called_once_with( 

5719 self.context, fake_host) 

5720 db_api.service_get_by_args.assert_called_once_with( 

5721 self.context, fake_host, 'manila-share') 

5722 db_api.availability_zone_get.assert_called_once_with( 

5723 self.context, service['availability_zone']['name'] 

5724 ) 

5725 (db_api.share_network_subnets_get_all_by_availability_zone_id. 

5726 assert_called_once_with( 

5727 self.context, fake_share_network_id, fake_az['id'])) 

5728 db_api.share_group_get_all_by_share_server.assert_called_once_with( 

5729 self.context, fake_share_server['id']) 

5730 

5731 def test__migration_initial_checks_share_in_share_group(self): 

5732 fake_share_server = fakes.fake_share_server_get() 

5733 fake_share_server['host'] = 'fake@backend' 

5734 type_data = { 

5735 'extra_specs': { 

5736 'availability_zones': 'fake_az1,fake_az2' 

5737 } 

5738 } 

5739 fake_server_host = 'fake@backend' 

5740 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5741 share_type = db_utils.create_share_type(**type_data) 

5742 share_type = db_api.share_type_get(self.context, share_type['id']) 

5743 fake_share = db_utils.create_share( 

5744 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

5745 share_type_id=share_type['id'], share_group_id='fake_group_id') 

5746 fake_az = { 

5747 'id': 'fake_az_id', 

5748 'name': 'fake_az1' 

5749 } 

5750 fake_share_network = None 

5751 fake_share_network_id = fake_share['share_network_id'] 

5752 fake_subnet = db_utils.create_share_network_subnet( 

5753 availability_zone_id=fake_az['id']) 

5754 fake_host = 'test@fake' 

5755 service = {'availability_zone_id': fake_az['id'], 

5756 'availability_zone': {'name': fake_az['name']}} 

5757 self._setup_mocks_for_initial_checks(fake_share, share_type, service, 

5758 fake_az, fake_subnet) 

5759 mock_snapshots_get = self.mock_object( 

5760 db_api, 'share_snapshot_get_all_for_share', 

5761 mock.Mock(return_value=[])) 

5762 

5763 self.assertRaises( 

5764 exception.InvalidShareServer, 

5765 self.api._migration_initial_checks, 

5766 self.context, fake_share_server, fake_host, fake_share_network, 

5767 ) 

5768 db_api.share_get_all_by_share_server.assert_has_calls([ 

5769 mock.call(self.context, fake_share_server['id']), 

5770 mock.call(self.context, fake_share_server['id'])]) 

5771 share_types.get_share_type.assert_called_once_with( 

5772 self.context, share_type['id']) 

5773 utils.validate_service_host.assert_called_once_with( 

5774 self.context, fake_host) 

5775 db_api.service_get_by_args.assert_called_once_with( 

5776 self.context, fake_host, 'manila-share') 

5777 db_api.availability_zone_get.assert_called_once_with( 

5778 self.context, service['availability_zone']['name'] 

5779 ) 

5780 (db_api.share_network_subnets_get_all_by_availability_zone_id. 

5781 assert_called_once_with( 

5782 self.context, fake_share_network_id, fake_az['id'])) 

5783 mock_snapshots_get.assert_called_once_with( 

5784 self.context, fake_share['id']) 

5785 db_api.share_group_get_all_by_share_server.assert_called_once_with( 

5786 self.context, fake_share_server['id']) 

5787 

5788 def test__migration_initial_checks_same_backend_and_network(self): 

5789 fake_server_host = 'fake@backend' 

5790 fake_share_network = {'id': 'fake_share_network_id'} 

5791 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5792 fake_share = db_utils.create_share( 

5793 host=fake_server_host, status=constants.STATUS_AVAILABLE, 

5794 share_group_id='fake_group_id', 

5795 share_network_id=fake_share_network['id']) 

5796 

5797 mock_shares_get_all = self.mock_object( 

5798 db_api, 'share_get_all_by_share_server', 

5799 mock.Mock(return_value=[fake_share])) 

5800 

5801 self.assertRaises( 

5802 exception.InvalidShareServer, 

5803 self.api._migration_initial_checks, 

5804 self.context, fake_share_server, fake_server_host, 

5805 fake_share_network, 

5806 ) 

5807 mock_shares_get_all.assert_called_once_with( 

5808 self.context, fake_share_server['id']) 

5809 

5810 def test__migration_initial_checks_another_migration_found(self): 

5811 fake_server_host = 'fake@backend2' 

5812 fake_share_network = {'id': 'fake_share_network_id'} 

5813 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5814 fake_share = db_utils.create_share( 

5815 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

5816 share_group_id='fake_group_id', share_network=fake_share_network) 

5817 

5818 mock_shares_get_all = self.mock_object( 

5819 db_api, 'share_get_all_by_share_server', 

5820 mock.Mock(return_value=[fake_share])) 

5821 mock_shares_get_servers_filters = self.mock_object( 

5822 db_api, 'share_server_get_all_with_filters', 

5823 mock.Mock(return_value=['fake_share_server'])) 

5824 

5825 self.assertRaises( 

5826 exception.InvalidShareServer, 

5827 self.api._migration_initial_checks, 

5828 self.context, fake_share_server, fake_server_host, 

5829 fake_share_network, 

5830 ) 

5831 mock_shares_get_all.assert_called_once_with( 

5832 self.context, fake_share_server['id']) 

5833 filters = {'source_share_server_id': fake_share_server['id'], 

5834 'status': constants.STATUS_SERVER_MIGRATING_TO} 

5835 mock_shares_get_servers_filters.assert_called_once_with( 

5836 self.context, filters=filters) 

5837 

5838 def test_share_server_migration_get_request_spec_dict(self): 

5839 share_instances = [ 

5840 db_utils.create_share_instance(share_id='fake_id') 

5841 for i in range(1, 3)] 

5842 snapshot_instances = [ 

5843 db_utils.create_snapshot_instance( 

5844 snapshot_id='fake_' + str(i), share_instance_id='fake') 

5845 for i in range(1, 3)] 

5846 shares_req_spec = [{} for instance in share_instances] 

5847 total_shares_size = sum( 

5848 [instance.get('size', 0) for instance in share_instances]) 

5849 total_snapshots_size = sum( 

5850 [instance.get('size', 0) for instance in snapshot_instances]) 

5851 expected_result = { 

5852 'shares_size': total_shares_size, 

5853 'snapshots_size': total_snapshots_size, 

5854 'shares_req_spec': shares_req_spec, 

5855 } 

5856 fake_share_type = db_utils.create_share_type() 

5857 get_type_calls = [] 

5858 get_request_spec_calls = [] 

5859 for instance in share_instances: 

5860 get_type_calls.append( 

5861 mock.call(self.context, instance['share_type_id'])) 

5862 get_request_spec_calls.append( 

5863 mock.call(self.context, instance, fake_share_type)) 

5864 

5865 mock_get_type = self.mock_object( 

5866 share_types, 'get_share_type', 

5867 mock.Mock(return_value=fake_share_type)) 

5868 mock_get_request_spec = self.mock_object( 

5869 self.api, '_get_request_spec_dict', mock.Mock(return_value={})) 

5870 

5871 result = self.api.get_share_server_migration_request_spec_dict( 

5872 self.context, share_instances, snapshot_instances) 

5873 

5874 self.assertEqual(result, expected_result) 

5875 mock_get_type.assert_has_calls(get_type_calls) 

5876 mock_get_request_spec.assert_has_calls(get_request_spec_calls) 

5877 

5878 def test__migration_initial_checks_instance_rules_error_status(self): 

5879 fake_share_server = fakes.fake_share_server_get() 

5880 fake_share_server['host'] = 'fake@backend' 

5881 type_data = { 

5882 'extra_specs': { 

5883 'availability_zones': 'fake_az1,fake_az2' 

5884 } 

5885 } 

5886 fake_server_host = 'fake@backend' 

5887 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5888 share_type = db_utils.create_share_type(**type_data) 

5889 share_type = db_api.share_type_get(self.context, share_type['id']) 

5890 fake_share = db_utils.create_share( 

5891 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

5892 share_type_id=share_type['id'], share_group_id='fake_group_id') 

5893 fake_share['instance']['access_rules_status'] = constants.STATUS_ERROR 

5894 fake_az = { 

5895 'id': 'fake_az_id', 

5896 'name': 'fake_az1' 

5897 } 

5898 fake_share_network = None 

5899 fake_share_network_id = fake_share['share_network_id'] 

5900 fake_subnet = db_utils.create_share_network_subnet( 

5901 availability_zone_id=fake_az['id']) 

5902 fake_host = 'test@fake' 

5903 service = {'availability_zone_id': fake_az['id'], 

5904 'availability_zone': {'name': fake_az['name']}} 

5905 self._setup_mocks_for_initial_checks(fake_share, share_type, service, 

5906 fake_az, fake_subnet) 

5907 

5908 mock_snapshots_get = self.mock_object( 

5909 db_api, 'share_snapshot_get_all_for_share', 

5910 mock.Mock(return_value=[])) 

5911 

5912 self.assertRaises( 

5913 exception.InvalidShareServer, 

5914 self.api._migration_initial_checks, 

5915 self.context, fake_share_server, fake_host, fake_share_network, 

5916 ) 

5917 

5918 db_api.share_get_all_by_share_server.assert_has_calls([ 

5919 mock.call(self.context, fake_share_server['id']), 

5920 mock.call(self.context, fake_share_server['id'])]) 

5921 share_types.get_share_type.assert_called_once_with( 

5922 self.context, share_type['id']) 

5923 utils.validate_service_host.assert_called_once_with( 

5924 self.context, fake_host) 

5925 db_api.service_get_by_args.assert_called_once_with( 

5926 self.context, fake_host, 'manila-share') 

5927 db_api.availability_zone_get.assert_called_once_with( 

5928 self.context, service['availability_zone']['name'] 

5929 ) 

5930 (db_api.share_network_subnets_get_all_by_availability_zone_id. 

5931 assert_called_once_with( 

5932 self.context, fake_share_network_id, fake_az['id'])) 

5933 mock_snapshots_get.assert_called_once_with( 

5934 self.context, fake_share['id']) 

5935 db_api.share_group_get_all_by_share_server.assert_called_once_with( 

5936 self.context, fake_share_server['id']) 

5937 

5938 def test__migration_initial_checks_dest_az_not_match_host_az(self): 

5939 type_data = { 

5940 'extra_specs': { 

5941 'availability_zones': 'zone1,zone2' 

5942 } 

5943 } 

5944 fake_server_host = 'fake@backend' 

5945 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5946 share_type = db_utils.create_share_type(**type_data) 

5947 share_type = db_api.share_type_get(self.context, share_type['id']) 

5948 fake_share = db_utils.create_share( 

5949 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

5950 share_type_id=share_type['id']) 

5951 fake_share_network = {} 

5952 fake_host = 'test@fake' 

5953 service = {'availability_zone_id': 'fake_az_id', 

5954 'availability_zone': {'name': 'fake_az1'}} 

5955 

5956 mock_shares_get_all = self.mock_object( 

5957 db_api, 'share_get_all_by_share_server', 

5958 mock.Mock(return_value=[fake_share])) 

5959 mock_get_type = self.mock_object( 

5960 share_types, 'get_share_type', mock.Mock(return_value=share_type)) 

5961 mock_validate_service = self.mock_object( 

5962 utils, 'validate_service_host') 

5963 mock_service_get = self.mock_object( 

5964 db_api, 'service_get_by_args', mock.Mock(return_value=service)) 

5965 

5966 self.assertRaises( 

5967 exception.InvalidShareServer, 

5968 self.api._migration_initial_checks, 

5969 self.context, fake_share_server, fake_host, fake_share_network, 

5970 ) 

5971 mock_shares_get_all.assert_called_once_with( 

5972 self.context, fake_share_server['id']) 

5973 mock_get_type.assert_called_once_with(self.context, share_type['id']) 

5974 mock_validate_service.assert_called_once_with(self.context, fake_host) 

5975 mock_service_get.assert_called_once_with( 

5976 self.context, fake_host, 'manila-share') 

5977 

5978 def test__migration_initial_checks_no_matching_subnet(self): 

5979 type_data = { 

5980 'extra_specs': { 

5981 'availability_zones': 'fake_az1,fake_az2' 

5982 } 

5983 } 

5984 fake_server_host = 'fake@backend' 

5985 fake_share_server = db_utils.create_share_server(host=fake_server_host) 

5986 share_type = db_utils.create_share_type(**type_data) 

5987 share_type = db_api.share_type_get(self.context, share_type['id']) 

5988 fake_share = db_utils.create_share( 

5989 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

5990 share_type_id=share_type['id']) 

5991 fake_share_network = db_utils.create_share_network() 

5992 fake_az = { 

5993 'id': 'fake_az_id', 

5994 'name': 'fake_az1' 

5995 } 

5996 

5997 db_utils.create_share_network_subnet( 

5998 availability_zone_id='fake', 

5999 share_network_id=fake_share_network['id']) 

6000 fake_share_network = db_api.share_network_get( 

6001 self.context, fake_share_network['id']) 

6002 fake_host = 'test@fake' 

6003 service = {'availability_zone_id': fake_az['id'], 

6004 'availability_zone': {'name': fake_az['name']}} 

6005 

6006 mock_shares_get_all = self.mock_object( 

6007 db_api, 'share_get_all_by_share_server', 

6008 mock.Mock(return_value=[fake_share])) 

6009 mock_get_type = self.mock_object( 

6010 share_types, 'get_share_type', mock.Mock(return_value=share_type)) 

6011 mock_validate_service = self.mock_object( 

6012 utils, 'validate_service_host') 

6013 mock_service_get = self.mock_object( 

6014 db_api, 'service_get_by_args', mock.Mock(return_value=service)) 

6015 mock_az_get = self.mock_object( 

6016 db_api, 'availability_zone_get', mock.Mock(return_value=fake_az)) 

6017 mock_get_subnet = self.mock_object( 

6018 db_api, 'share_network_subnets_get_all_by_availability_zone_id', 

6019 mock.Mock(return_value=None)) 

6020 

6021 self.assertRaises( 

6022 exception.InvalidShareServer, 

6023 self.api._migration_initial_checks, 

6024 self.context, fake_share_server, fake_host, fake_share_network, 

6025 ) 

6026 mock_shares_get_all.assert_called_once_with( 

6027 self.context, fake_share_server['id']) 

6028 mock_get_type.assert_called_once_with(self.context, share_type['id']) 

6029 mock_validate_service.assert_called_once_with(self.context, fake_host) 

6030 mock_service_get.assert_called_once_with( 

6031 self.context, fake_host, 'manila-share') 

6032 mock_get_subnet.assert_called_once_with( 

6033 self.context, fake_share_network['id'], fake_az['id']) 

6034 mock_az_get.assert_called_once_with( 

6035 self.context, service['availability_zone']['name'] 

6036 ) 

6037 

6038 def test_server_migration_check_nondisruptive_and_network_change(self): 

6039 fake_shares = [db_utils.create_share() for i in range(2)] 

6040 fake_types = [{'id': 'fake_type_id'}] 

6041 fake_share_server = db_utils.create_share_server() 

6042 dest_host = fake_share_server['host'] 

6043 service = { 

6044 'availability_zone_id': 'fake_az_id', 

6045 'availability_zone': {'name': 'fake_az_name'} 

6046 } 

6047 fake_share_network = db_utils.create_share_network() 

6048 network_has_changed = True 

6049 writable = preserve_snapshots = False 

6050 nondisruptive = True 

6051 expected_result = { 

6052 'compatible': False, 

6053 'writable': writable, 

6054 'nondisruptive': False, 

6055 'preserve_snapshots': preserve_snapshots, 

6056 'share_network_id': fake_share_network['id'], 

6057 'migration_cancel': False, 

6058 'migration_get_progress': False 

6059 } 

6060 

6061 mock_initial_checks = self.mock_object( 

6062 self.api, '_migration_initial_checks', 

6063 mock.Mock( 

6064 return_value=[fake_shares, fake_types, service, 

6065 fake_share_network['id'], network_has_changed])) 

6066 

6067 check_result = self.api.share_server_migration_check( 

6068 self.context, fake_share_server, dest_host, writable, 

6069 nondisruptive, preserve_snapshots, fake_share_network 

6070 ) 

6071 

6072 self.assertEqual(expected_result, check_result) 

6073 mock_initial_checks.assert_called_once_with( 

6074 self.context, fake_share_server, dest_host, fake_share_network) 

6075 

6076 def test_server_migration_start_nondisruptive_and_network_change(self): 

6077 fake_shares = [db_utils.create_share() for i in range(2)] 

6078 fake_types = [{'id': 'fake_type_id'}] 

6079 fake_share_server = db_utils.create_share_server() 

6080 dest_host = fake_share_server['host'] 

6081 service = { 

6082 'availability_zone_id': 'fake_az_id', 

6083 'availability_zone': {'name': 'fake_az_name'} 

6084 } 

6085 fake_share_network = db_utils.create_share_network() 

6086 network_has_changed = True 

6087 writable = preserve_snapshots = False 

6088 nondisruptive = True 

6089 

6090 mock_initial_checks = self.mock_object( 

6091 self.api, '_migration_initial_checks', 

6092 mock.Mock( 

6093 return_value=[fake_shares, fake_types, service, 

6094 fake_share_network['id'], network_has_changed])) 

6095 

6096 self.assertRaises( 

6097 exception.InvalidInput, 

6098 self.api.share_server_migration_start, 

6099 self.context, fake_share_server, dest_host, writable, 

6100 nondisruptive, preserve_snapshots, fake_share_network 

6101 ) 

6102 

6103 mock_initial_checks.assert_called_once_with( 

6104 self.context, fake_share_server, dest_host, fake_share_network) 

6105 

6106 def test_share_server_migration_check(self): 

6107 type_data = { 

6108 'extra_specs': { 

6109 'availability_zones': 'fake_az1,fake_az2' 

6110 } 

6111 } 

6112 fake_share_server = db_utils.create_share_server() 

6113 share_type = db_utils.create_share_type(**type_data) 

6114 share_type = db_api.share_type_get(self.context, share_type['id']) 

6115 fake_share = db_utils.create_share( 

6116 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

6117 share_type_id=share_type['id']) 

6118 fake_shares = [fake_share] 

6119 fake_types = [share_type] 

6120 fake_share_network = db_utils.create_share_network() 

6121 fake_az = { 

6122 'id': 'fake_az_id', 

6123 'name': 'fake_az1' 

6124 } 

6125 writable = True 

6126 nondisruptive = True 

6127 preserve_snapshots = True 

6128 fake_share_network = db_api.share_network_get( 

6129 self.context, fake_share_network['id']) 

6130 fake_host = 'test@fake' 

6131 service = {'availability_zone_id': fake_az['id'], 

6132 'availability_zone': {'name': fake_az['name']}} 

6133 expected_result = { 

6134 'requested_capabilities': {}, 

6135 'supported_capabilities': {} 

6136 } 

6137 

6138 mock_initial_checks = self.mock_object( 

6139 self.api, '_migration_initial_checks', 

6140 mock.Mock(return_value=[fake_shares, fake_types, service, 

6141 fake_share_network['id'], False])) 

6142 # NOTE(carloss): Returning an "empty" dictionary should be enough for 

6143 # this test case. The unit test to check the values being returned to 

6144 # the user should be placed in the share manager, where the dict is 

6145 # populated with the real info. At this level we only forward the 

6146 # received response to the user. 

6147 mock_migration_check = self.mock_object( 

6148 self.share_rpcapi, 'share_server_migration_check', 

6149 mock.Mock(return_value=expected_result)) 

6150 

6151 result = self.api.share_server_migration_check( 

6152 self.context, fake_share_server, fake_host, writable, 

6153 nondisruptive, preserve_snapshots, fake_share_network 

6154 ) 

6155 

6156 mock_initial_checks.assert_called_once_with( 

6157 self.context, fake_share_server, fake_host, fake_share_network) 

6158 mock_migration_check.assert_called_once_with( 

6159 self.context, fake_share_server['id'], fake_host, writable, 

6160 nondisruptive, preserve_snapshots, fake_share_network['id'] 

6161 ) 

6162 self.assertEqual(result, expected_result) 

6163 

6164 def test_share_server_migration_start(self): 

6165 type_data = { 

6166 'extra_specs': { 

6167 'availability_zones': 'fake_az1,fake_az2' 

6168 } 

6169 } 

6170 fake_share_server = db_utils.create_share_server() 

6171 share_type = db_utils.create_share_type(**type_data) 

6172 share_type = db_api.share_type_get(self.context, share_type['id']) 

6173 fake_shares = [db_utils.create_share( 

6174 host='fake@backend#pool', status=constants.STATUS_AVAILABLE, 

6175 share_type_id=share_type['id'], 

6176 share_server_id=fake_share_server['id']) for x in range(4)] 

6177 fake_snapshots = [ 

6178 db_utils.create_snapshot(share_id=fake_shares[0]['id'])] 

6179 instance_ids = [share['instance']['id'] for share in fake_shares] 

6180 snap_instances = [] 

6181 snap_instance_ids = [] 

6182 for fake_share in fake_shares: 

6183 for snapshot in fake_snapshots: 

6184 snap_instances.append({'id': snapshot['instance']['id']}) 

6185 snap_instance_ids.append(snapshot['instance']['id']) 

6186 fake_types = [share_type] 

6187 fake_share_network = db_utils.create_share_network() 

6188 writable = True 

6189 nondisruptive = True 

6190 preserve_snapshots = True 

6191 fake_share_network = db_api.share_network_get( 

6192 self.context, fake_share_network['id']) 

6193 fake_host = 'test@fake' 

6194 service = {'availability_zone_id': 'fake_az_id', 

6195 'availability_zone': {'name': 'fake_az1'}} 

6196 server_expected_update = { 

6197 'task_state': constants.TASK_STATE_MIGRATION_STARTING, 

6198 'status': constants.STATUS_SERVER_MIGRATING 

6199 } 

6200 share_expected_update = { 

6201 'status': constants.STATUS_SERVER_MIGRATING 

6202 } 

6203 mock_initial_checks = self.mock_object( 

6204 self.api, '_migration_initial_checks', 

6205 mock.Mock(return_value=[fake_shares, fake_types, service, 

6206 fake_share_network['id'], False])) 

6207 mock_migration_start = self.mock_object( 

6208 self.share_rpcapi, 'share_server_migration_start') 

6209 mock_server_update = self.mock_object(db_api, 'share_server_update') 

6210 mock_snapshots_get = self.mock_object( 

6211 db_api, 'share_snapshot_instance_get_all_with_filters', 

6212 mock.Mock(return_value=snap_instances)) 

6213 mock_update_instances = self.mock_object( 

6214 db_api, 'share_and_snapshot_instances_status_update') 

6215 

6216 self.api.share_server_migration_start( 

6217 self.context, fake_share_server, fake_host, writable, 

6218 nondisruptive, preserve_snapshots, fake_share_network 

6219 ) 

6220 

6221 mock_initial_checks.assert_called_once_with( 

6222 self.context, fake_share_server, fake_host, fake_share_network) 

6223 mock_migration_start.assert_called_once_with( 

6224 self.context, fake_share_server, fake_host, writable, 

6225 nondisruptive, preserve_snapshots, fake_share_network['id'] 

6226 ) 

6227 mock_server_update.assert_called_once_with( 

6228 self.context, fake_share_server['id'], server_expected_update) 

6229 mock_snapshots_get.assert_called() 

6230 mock_update_instances.assert_called_once_with( 

6231 self.context, share_expected_update, 

6232 current_expected_status=constants.STATUS_AVAILABLE, 

6233 share_instance_ids=instance_ids, 

6234 snapshot_instance_ids=snap_instance_ids) 

6235 

6236 @ddt.data( 

6237 (constants.STATUS_ACTIVE, None), 

6238 (constants.STATUS_SERVER_MIGRATING, 

6239 constants.TASK_STATE_MIGRATION_STARTING) 

6240 ) 

6241 @ddt.unpack 

6242 def test_share_server_migration_complete_invalid_status(self, status, 

6243 task_state): 

6244 fake_host = 'fakehost@fakebackend' 

6245 fake_share_server = db_utils.create_share_server( 

6246 status=status, task_state=task_state, host=fake_host) 

6247 self.assertRaises( 

6248 exception.InvalidShareServer, 

6249 self.api.share_server_migration_complete, 

6250 self.context, fake_share_server) 

6251 

6252 def test_share_server_migration_complete(self): 

6253 fake_service_host = 'fakehost@fakebackend' 

6254 fake_share_server = db_utils.create_share_server( 

6255 status=constants.STATUS_SERVER_MIGRATING, 

6256 task_state=constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE, 

6257 host=fake_service_host) 

6258 fake_share_server_dest = db_utils.create_share_server( 

6259 status=constants.STATUS_SERVER_MIGRATING_TO, 

6260 host=fake_service_host) 

6261 fake_service = {'availability_zone_id': 'fake_az_id', 

6262 'availability_zone': {'name': 'fake_az1'}} 

6263 

6264 mock_get_destination = self.mock_object( 

6265 self.api, 'share_server_migration_get_destination', 

6266 mock.Mock(return_value=fake_share_server_dest)) 

6267 mock_validate_service_host = self.mock_object( 

6268 utils, 'validate_service_host', 

6269 mock.Mock(return_value=fake_service)) 

6270 mock_migration_complete = self.mock_object( 

6271 self.share_rpcapi, 'share_server_migration_complete') 

6272 

6273 result = self.api.share_server_migration_complete( 

6274 self.context, fake_share_server) 

6275 

6276 expected = { 

6277 'destination_share_server_id': fake_share_server_dest['id'] 

6278 } 

6279 self.assertEqual(expected, result) 

6280 mock_get_destination.assert_called_once_with( 

6281 self.context, fake_share_server['id'], 

6282 status=constants.STATUS_SERVER_MIGRATING_TO) 

6283 mock_validate_service_host.assert_called_once_with( 

6284 self.context, fake_service_host) 

6285 mock_migration_complete.assert_called_once_with( 

6286 self.context, fake_share_server['host'], fake_share_server, 

6287 fake_share_server_dest 

6288 ) 

6289 

6290 @ddt.data( 

6291 (constants.STATUS_ACTIVE, None), 

6292 (constants.STATUS_SERVER_MIGRATING, 

6293 constants.TASK_STATE_MIGRATION_STARTING) 

6294 ) 

6295 @ddt.unpack 

6296 def test_share_server_migration_cancel_server_not_migrating( 

6297 self, status, task_state): 

6298 fake_share_server = db_utils.create_share_server( 

6299 status=status, task_state=task_state) 

6300 

6301 self.mock_object(self.api, '_migration_validate_error_message', 

6302 mock.Mock(return_value=None)) 

6303 

6304 self.assertRaises( 

6305 exception.InvalidShareServer, 

6306 self.api.share_server_migration_cancel, 

6307 self.context, 

6308 fake_share_server 

6309 ) 

6310 

6311 @ddt.data(constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE, 

6312 constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS) 

6313 def test_share_server_migration_cancel_service_not_up(self, task_state): 

6314 fake_service_host = 'host@backend' 

6315 fake_share_server = db_utils.create_share_server( 

6316 status=constants.STATUS_SERVER_MIGRATING, 

6317 task_state=task_state, 

6318 host=fake_service_host) 

6319 fake_share_server_dest = db_utils.create_share_server( 

6320 status=constants.STATUS_SERVER_MIGRATING_TO, 

6321 host=fake_service_host) 

6322 

6323 mock_get_destination = self.mock_object( 

6324 self.api, 'share_server_migration_get_destination', 

6325 mock.Mock(return_value=fake_share_server_dest)) 

6326 mock_validate_service_host = self.mock_object( 

6327 utils, 'validate_service_host', 

6328 mock.Mock(side_effect=exception.ServiceIsDown( 

6329 service="fake_service"))) 

6330 

6331 self.assertRaises( 

6332 exception.ServiceIsDown, 

6333 self.api.share_server_migration_cancel, 

6334 self.context, 

6335 fake_share_server 

6336 ) 

6337 mock_get_destination.assert_called_once_with( 

6338 self.context, fake_share_server['id'], 

6339 status=constants.STATUS_SERVER_MIGRATING_TO) 

6340 mock_validate_service_host.assert_called_once_with( 

6341 self.context, fake_service_host) 

6342 

6343 @ddt.data(constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE, 

6344 constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS) 

6345 def test_share_server_migration_cancel(self, task_state): 

6346 fake_service_host = 'host@backend' 

6347 fake_share_server = db_utils.create_share_server( 

6348 status=constants.STATUS_SERVER_MIGRATING, 

6349 task_state=task_state, 

6350 host=fake_service_host) 

6351 fake_share_server_dest = db_utils.create_share_server( 

6352 status=constants.STATUS_SERVER_MIGRATING_TO, 

6353 host=fake_service_host) 

6354 fake_service = {'availability_zone_id': 'fake_az_id', 

6355 'availability_zone': {'name': 'fake_az1'}} 

6356 

6357 mock_get_destination = self.mock_object( 

6358 self.api, 'share_server_migration_get_destination', 

6359 mock.Mock(return_value=fake_share_server_dest)) 

6360 mock_validate_service_host = self.mock_object( 

6361 utils, 'validate_service_host', 

6362 mock.Mock(return_value=fake_service)) 

6363 

6364 self.api.share_server_migration_cancel( 

6365 self.context, fake_share_server) 

6366 

6367 mock_get_destination.assert_called_once_with( 

6368 self.context, fake_share_server['id'], 

6369 status=constants.STATUS_SERVER_MIGRATING_TO) 

6370 mock_validate_service_host.assert_called_once_with( 

6371 self.context, fake_service_host) 

6372 

6373 def test_share_server_migration_get_progress_not_migrating(self): 

6374 fake_share_server = db_utils.create_share_server( 

6375 status=constants.STATUS_ACTIVE) 

6376 self.assertRaises( 

6377 exception.InvalidShareServer, 

6378 self.api.share_server_migration_get_progress, 

6379 self.context, fake_share_server['id'] 

6380 ) 

6381 

6382 def test_share_server_migration_get_progress_service_not_up(self): 

6383 fake_service_host = 'host@backend' 

6384 fake_share_server = db_utils.create_share_server( 

6385 status=constants.STATUS_SERVER_MIGRATING, 

6386 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

6387 host=fake_service_host) 

6388 fake_share_server_dest = db_utils.create_share_server( 

6389 status=constants.STATUS_SERVER_MIGRATING_TO, 

6390 host=fake_service_host) 

6391 

6392 mock_get_destination = self.mock_object( 

6393 self.api, 'share_server_migration_get_destination', 

6394 mock.Mock(return_value=fake_share_server_dest)) 

6395 mock_validate_service_host = self.mock_object( 

6396 utils, 'validate_service_host', 

6397 mock.Mock(side_effect=exception.ServiceIsDown( 

6398 service="fake_service"))) 

6399 

6400 self.assertRaises( 

6401 exception.ServiceIsDown, 

6402 self.api.share_server_migration_get_progress, 

6403 self.context, fake_share_server['id'] 

6404 ) 

6405 

6406 mock_get_destination.assert_called_once_with( 

6407 self.context, fake_share_server['id'], 

6408 status=constants.STATUS_SERVER_MIGRATING_TO) 

6409 mock_validate_service_host.assert_called_once_with( 

6410 self.context, fake_service_host) 

6411 

6412 def test_share_server_migration_get_progress_rpcapi_exception(self): 

6413 fake_service_host = 'host@backend' 

6414 fake_share_server = db_utils.create_share_server( 

6415 status=constants.STATUS_SERVER_MIGRATING, 

6416 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

6417 host=fake_service_host) 

6418 fake_share_server_dest = db_utils.create_share_server( 

6419 status=constants.STATUS_SERVER_MIGRATING_TO, 

6420 host=fake_service_host) 

6421 fake_service = {'availability_zone_id': 'fake_az_id', 

6422 'availability_zone': {'name': 'fake_az1'}} 

6423 

6424 mock_server_get = self.mock_object( 

6425 db_api, 'share_server_get', 

6426 mock.Mock(return_value=fake_share_server)) 

6427 mock_get_destination = self.mock_object( 

6428 self.api, 'share_server_migration_get_destination', 

6429 mock.Mock(return_value=fake_share_server_dest)) 

6430 mock_validate_service_host = self.mock_object( 

6431 utils, 'validate_service_host', 

6432 mock.Mock(return_value=fake_service)) 

6433 mock_migration_get_progress = self.mock_object( 

6434 self.share_rpcapi, 'share_server_migration_get_progress', 

6435 mock.Mock(side_effect=Exception)) 

6436 

6437 self.assertRaises( 

6438 exception.ShareServerMigrationError, 

6439 self.api.share_server_migration_get_progress, 

6440 self.context, 

6441 fake_share_server['id'] 

6442 ) 

6443 

6444 mock_server_get.assert_called_once_with(self.context, 

6445 fake_share_server['id']) 

6446 mock_get_destination.assert_called_once_with( 

6447 self.context, fake_share_server['id'], 

6448 status=constants.STATUS_SERVER_MIGRATING_TO) 

6449 mock_validate_service_host.assert_called_once_with( 

6450 self.context, fake_service_host) 

6451 mock_migration_get_progress.assert_called_once_with( 

6452 self.context, fake_share_server_dest['host'], fake_share_server, 

6453 fake_share_server_dest) 

6454 

6455 @ddt.data(constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

6456 constants.TASK_STATE_MIGRATION_SUCCESS) 

6457 def test_share_server_migration_get_progress(self, task_state): 

6458 fake_service_host = 'host@backend' 

6459 fake_share_server = db_utils.create_share_server( 

6460 status=constants.STATUS_SERVER_MIGRATING, 

6461 task_state=task_state, host=fake_service_host) 

6462 fake_share_server_dest = db_utils.create_share_server( 

6463 status=constants.STATUS_SERVER_MIGRATING_TO, 

6464 host=fake_service_host) 

6465 fake_service = {'availability_zone_id': 'fake_az_id', 

6466 'availability_zone': {'name': 'fake_az1'}} 

6467 

6468 mock_server_get = self.mock_object( 

6469 db_api, 'share_server_get', 

6470 mock.Mock(return_value=fake_share_server)) 

6471 mock_get_destination = self.mock_object( 

6472 self.api, 'share_server_migration_get_destination', 

6473 mock.Mock(return_value=fake_share_server_dest)) 

6474 mock_validate_service_host = self.mock_object( 

6475 utils, 'validate_service_host', 

6476 mock.Mock(return_value=fake_service)) 

6477 mock_migration_get_progress = self.mock_object( 

6478 self.share_rpcapi, 'share_server_migration_get_progress', 

6479 mock.Mock(return_value={'total_progress': 50})) 

6480 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

6481 

6482 result = self.api.share_server_migration_get_progress( 

6483 self.context, fake_share_server['id']) 

6484 

6485 self.assertIn('total_progress', result) 

6486 mock_server_get.assert_called_once_with(self.context, 

6487 fake_share_server['id']) 

6488 if task_state == constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS: 

6489 mock_get_destination.assert_called_once_with( 

6490 self.context, fake_share_server['id'], 

6491 status=constants.STATUS_SERVER_MIGRATING_TO) 

6492 mock_validate_service_host.assert_called_once_with( 

6493 self.context, fake_service_host) 

6494 mock_migration_get_progress.assert_called_once_with( 

6495 self.context, fake_share_server_dest['host'], 

6496 fake_share_server, fake_share_server_dest) 

6497 

6498 @ddt.data(constants.STATUS_SERVER_MIGRATING_TO, 

6499 constants.STATUS_SERVER_MIGRATING) 

6500 def test_share_server_migration_get_progress_invalid_share_server(self, 

6501 status): 

6502 fake_service_host = 'host@backend' 

6503 fake_share_server = db_utils.create_share_server( 

6504 status=status, 

6505 task_state=None, 

6506 host=fake_service_host) 

6507 mock_server_get = self.mock_object( 

6508 db_api, 'share_server_get', 

6509 mock.Mock(return_value=fake_share_server)) 

6510 mock_get_progress_state = self.mock_object( 

6511 self.api, '_migration_get_progress_state', 

6512 mock.Mock(return_value=None)) 

6513 self.mock_object(self.api, 'share_server_migration_get_destination') 

6514 

6515 self.assertRaises( 

6516 exception.InvalidShareServer, 

6517 self.api.share_server_migration_get_progress, 

6518 self.context, fake_share_server['id']) 

6519 

6520 mock_server_get.assert_called_once_with(self.context, 

6521 fake_share_server['id']) 

6522 if status == constants.STATUS_SERVER_MIGRATING: 

6523 mock_get_progress_state.assert_called_once_with(fake_share_server) 

6524 

6525 def test_share_server_migration_get_progress_source_not_found(self): 

6526 fake_dest_hare_server = db_utils.create_share_server( 

6527 status=constants.STATUS_ACTIVE, 

6528 task_state=constants.TASK_STATE_MIGRATION_SUCCESS) 

6529 mock_server_get = self.mock_object( 

6530 db_api, 'share_server_get', 

6531 mock.Mock(side_effect=exception.ShareServerNotFound( 

6532 share_server_id='fake_id'))) 

6533 mock_get_destination = self.mock_object( 

6534 self.api, 'share_server_migration_get_destination', 

6535 mock.Mock(return_value=fake_dest_hare_server)) 

6536 

6537 result = self.api.share_server_migration_get_progress( 

6538 self.context, 'fake_source_server_id') 

6539 expected = { 

6540 'total_progress': 100, 

6541 'destination_share_server_id': fake_dest_hare_server['id'], 

6542 'task_state': constants.TASK_STATE_MIGRATION_SUCCESS, 

6543 } 

6544 

6545 self.assertEqual(expected, result) 

6546 mock_server_get.assert_called_once_with(self.context, 

6547 'fake_source_server_id') 

6548 mock_get_destination.assert_called_once_with( 

6549 self.context, 'fake_source_server_id', 

6550 status=constants.STATUS_ACTIVE) 

6551 

6552 def test_share_server_migration_get_progress_has_destination_only(self): 

6553 mock_server_get = self.mock_object( 

6554 db_api, 'share_server_get', 

6555 mock.Mock(side_effect=exception.ShareServerNotFound( 

6556 share_server_id='fake_id'))) 

6557 mock_get_destination = self.mock_object( 

6558 self.api, 'share_server_migration_get_destination', 

6559 mock.Mock(side_effect=exception.InvalidShareServer(reason=''))) 

6560 

6561 self.assertRaises( 

6562 exception.InvalidShareServer, 

6563 self.api.share_server_migration_get_progress, 

6564 self.context, 'fake_src_server_id') 

6565 

6566 mock_server_get.assert_called_once_with(self.context, 

6567 'fake_src_server_id') 

6568 mock_get_destination.assert_called_once_with( 

6569 self.context, 'fake_src_server_id', status=constants.STATUS_ACTIVE) 

6570 

6571 def test_share_server_migration_get_progress_not_determinated(self): 

6572 fake_service_host = 'host@backend' 

6573 fake_share_server = db_utils.create_share_server( 

6574 status=constants.STATUS_SERVER_MIGRATING, 

6575 task_state=None, 

6576 host=fake_service_host) 

6577 mock_server_get = self.mock_object( 

6578 db_api, 'share_server_get', 

6579 mock.Mock(return_value=fake_share_server)) 

6580 mock_get_destination = self.mock_object( 

6581 self.api, 'share_server_migration_get_destination', 

6582 mock.Mock(side_effect=exception.InvalidShareServer(reason=''))) 

6583 mock_get_progress_state = self.mock_object( 

6584 self.api, '_migration_get_progress_state', 

6585 mock.Mock(return_value={'total_progress': 0})) 

6586 

6587 result = self.api.share_server_migration_get_progress( 

6588 self.context, 'fake_source_server_id') 

6589 

6590 expected = { 

6591 'total_progress': 0, 

6592 'destination_share_server_id': '', 

6593 'task_state': '', 

6594 } 

6595 

6596 self.assertEqual(expected, result) 

6597 mock_server_get.assert_called_once_with(self.context, 

6598 'fake_source_server_id') 

6599 mock_get_destination.assert_called_once_with( 

6600 self.context, fake_share_server['id'], 

6601 status=constants.STATUS_SERVER_MIGRATING_TO) 

6602 mock_get_progress_state.assert_called_once_with(fake_share_server) 

6603 

6604 def test_migration_get_progress_race(self): 

6605 

6606 instance1 = db_utils.create_share_instance( 

6607 share_id='fake_id', 

6608 status=constants.STATUS_MIGRATING, 

6609 host='some_host') 

6610 instance2 = db_utils.create_share_instance( 

6611 share_id='fake_id', 

6612 status=constants.STATUS_MIGRATING_TO) 

6613 share = db_utils.create_share( 

6614 id='fake_id', 

6615 task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS, 

6616 instances=[instance1, instance2]) 

6617 share_ref = fakes.fake_share( 

6618 id='fake_id', 

6619 task_state=constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE) 

6620 service = 'fake_service' 

6621 expected = {'total_progress': 100} 

6622 

6623 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

6624 self.mock_object(db_api, 'service_get_by_args', 

6625 mock.Mock(return_value=service)) 

6626 self.mock_object(db_api, 'share_instance_get', 

6627 mock.Mock(return_value=instance1)) 

6628 self.mock_object(db_api, 'share_get', 

6629 mock.Mock(return_value=share_ref)) 

6630 self.mock_object(self.api.share_rpcapi, 'migration_get_progress', 

6631 mock.Mock(side_effect=exception.InvalidShare('fake'))) 

6632 

6633 result = self.api.migration_get_progress(self.context, share) 

6634 self.assertEqual(expected, result) 

6635 

6636 self.api.share_rpcapi.migration_get_progress.assert_called_once_with( 

6637 self.context, instance1, instance2['id']) 

6638 

6639 def test__share_network_update_initial_checks_network_not_active(self): 

6640 share_network = db_utils.create_share_network( 

6641 status=constants.STATUS_NETWORK_CHANGE) 

6642 new_sec_service = db_utils.create_security_service( 

6643 share_network_id=share_network['id'], type='ldap') 

6644 

6645 self.assertRaises( 

6646 webob_exc.HTTPBadRequest, 

6647 self.api._share_network_update_initial_checks, 

6648 self.context, share_network, new_sec_service 

6649 ) 

6650 

6651 def test__share_network_update_initial_checks_server_not_active(self): 

6652 share_subnet = db_utils.create_share_network_subnet( 

6653 id='fakeid', share_network_id='fakenetid') 

6654 db_utils.create_share_server( 

6655 share_network_subnets=[share_subnet], 

6656 status=constants.STATUS_ERROR, 

6657 security_service_update_support=True) 

6658 share_network = db_utils.create_share_network(id='fakenetid') 

6659 new_sec_service = db_utils.create_security_service( 

6660 share_network_id='fakenetid', type='ldap') 

6661 

6662 self.assertRaises( 

6663 exception.InvalidShareNetwork, 

6664 self.api._share_network_update_initial_checks, 

6665 self.context, share_network, new_sec_service, 

6666 ) 

6667 

6668 def test__share_network_update_initial_checks_shares_not_available(self): 

6669 share_subnet = db_utils.create_share_network_subnet( 

6670 id='fakeid', share_network_id='fake_network_id') 

6671 db_utils.create_share_server(share_network_subnets=[share_subnet], 

6672 security_service_update_support=True) 

6673 share_network = db_utils.create_share_network( 

6674 id='fake_network_id') 

6675 new_sec_service = db_utils.create_security_service( 

6676 share_network_id='fake_network_id', type='ldap') 

6677 shares = [db_utils.create_share(status=constants.STATUS_ERROR)] 

6678 

6679 self.mock_object(utils, 'validate_service_host') 

6680 self.mock_object( 

6681 self.api, 'get_all', mock.Mock(return_value=shares)) 

6682 

6683 self.assertRaises( 

6684 exception.InvalidShareNetwork, 

6685 self.api._share_network_update_initial_checks, 

6686 self.context, share_network, new_sec_service 

6687 ) 

6688 utils.validate_service_host.assert_called_once_with( 

6689 utils.IsAMatcher(context.RequestContext), 'host1') 

6690 self.api.get_all.assert_called_once_with( 

6691 self.context, 

6692 search_opts={'share_network_id': share_network['id']}) 

6693 

6694 def test__share_network_update_initial_checks_rules_in_error(self): 

6695 share_subnet = db_utils.create_share_network_subnet( 

6696 id='fakeid', share_network_id='fake_network_id') 

6697 db_utils.create_share_server(share_network_subnets=[share_subnet], 

6698 security_service_update_support=True) 

6699 share_network = db_utils.create_share_network( 

6700 id='fake_network_id') 

6701 new_sec_service = db_utils.create_security_service( 

6702 share_network_id='fake_network_id', type='ldap') 

6703 shares = [db_utils.create_share(status=constants.STATUS_AVAILABLE)] 

6704 shares[0]['instance']['access_rules_status'] = ( 

6705 constants.ACCESS_STATE_ERROR) 

6706 

6707 self.mock_object(utils, 'validate_service_host') 

6708 self.mock_object( 

6709 self.api, 'get_all', mock.Mock(return_value=shares)) 

6710 

6711 self.assertRaises( 

6712 exception.InvalidShareNetwork, 

6713 self.api._share_network_update_initial_checks, 

6714 self.context, share_network, new_sec_service 

6715 ) 

6716 utils.validate_service_host.assert_called_once_with( 

6717 utils.IsAMatcher(context.RequestContext), 'host1') 

6718 self.api.get_all.assert_called_once_with( 

6719 self.context, 

6720 search_opts={'share_network_id': share_network['id']}) 

6721 

6722 def test__share_network_update_initial_checks_share_is_busy(self): 

6723 share_subnet = db_utils.create_share_network_subnet( 

6724 id='fakeid', share_network_id='fake_net_id') 

6725 db_utils.create_share_server(share_network_subnets=[share_subnet], 

6726 security_service_update_support=True) 

6727 share_network = db_utils.create_share_network(id='fake_net_id') 

6728 new_sec_service = db_utils.create_security_service( 

6729 share_network_id='fake_net_id', type='ldap') 

6730 shares = [db_utils.create_share(status=constants.STATUS_AVAILABLE)] 

6731 

6732 self.mock_object(utils, 'validate_service_host') 

6733 self.mock_object( 

6734 self.api, 'get_all', mock.Mock(return_value=shares)) 

6735 self.mock_object( 

6736 self.api, '_check_is_share_busy', 

6737 mock.Mock(side_effect=exception.ShareBusyException(message='fake')) 

6738 ) 

6739 

6740 self.assertRaises( 

6741 exception.InvalidShareNetwork, 

6742 self.api._share_network_update_initial_checks, 

6743 self.context, share_network, new_sec_service 

6744 ) 

6745 utils.validate_service_host.assert_called_once_with( 

6746 utils.IsAMatcher(context.RequestContext), 'host1') 

6747 self.api.get_all.assert_called_once_with( 

6748 self.context, 

6749 search_opts={'share_network_id': share_network['id']}) 

6750 self.api._check_is_share_busy.assert_called_once_with(shares[0]) 

6751 

6752 def test__share_network_update_initial_checks_unsupported_server(self): 

6753 share_subnet = db_utils.create_share_network_subnet( 

6754 id='fakeid', share_network_id='fake_net_id') 

6755 db_utils.create_share_server(share_network_subnets=[share_subnet], 

6756 security_service_update_support=False) 

6757 share_network = db_utils.create_share_network(id='fake_net_id') 

6758 

6759 self.assertRaises( 

6760 exception.InvalidShareNetwork, 

6761 self.api._share_network_update_initial_checks, 

6762 self.context, share_network, None 

6763 ) 

6764 

6765 def test__share_network_update_initial_checks_update_different_types(self): 

6766 db_utils.create_share_server(share_network_subnet_id='fakeid', 

6767 security_service_update_support=True) 

6768 db_utils.create_share_network_subnet( 

6769 id='fakeid', share_network_id='fake_net_id') 

6770 share_network = db_utils.create_share_network(id='fake_net_id') 

6771 new_sec_service = db_utils.create_security_service( 

6772 share_network_id='fake_net_id', type='ldap') 

6773 curr_sec_service = db_utils.create_security_service( 

6774 share_network_id='fake_net_id', type='kerberos') 

6775 

6776 self.assertRaises( 

6777 exception.InvalidSecurityService, 

6778 self.api._share_network_update_initial_checks, 

6779 self.context, share_network, new_sec_service, 

6780 current_security_service=curr_sec_service 

6781 ) 

6782 

6783 def test__share_network_update_initial_checks_add_type_conflict(self): 

6784 db_utils.create_share_server(share_network_subnet_id='fakeid', 

6785 security_service_update_support=True) 

6786 db_utils.create_share_network_subnet( 

6787 id='fakeid', share_network_id='fake_net_id') 

6788 share_network = db_utils.create_share_network(id='fake_net_id') 

6789 db_utils.create_security_service( 

6790 share_network_id='fake_net_id', type='ldap') 

6791 share_network = db_api.share_network_get(self.context, 

6792 share_network['id']) 

6793 new_sec_service = db_utils.create_security_service( 

6794 share_network_id='fake_net_id', type='ldap') 

6795 

6796 self.assertRaises( 

6797 exception.InvalidSecurityService, 

6798 self.api._share_network_update_initial_checks, 

6799 self.context, share_network, new_sec_service, 

6800 ) 

6801 

6802 def test_update_share_network_security_service_no_share_servers(self): 

6803 mock_initial_checks = self.mock_object( 

6804 self.api, '_share_network_update_initial_checks', 

6805 mock.Mock(return_value=([], []))) 

6806 mock_get_key = self.mock_object( 

6807 self.api, 'get_security_service_update_key') 

6808 fake_share_network = {'id': 'fake_share_net_id'} 

6809 fake_sec_service = {'id': 'fake_sec_serv_id'} 

6810 

6811 self.api.update_share_network_security_service( 

6812 self.context, fake_share_network, fake_sec_service, 

6813 current_security_service=None) 

6814 

6815 mock_initial_checks.assert_called_once_with( 

6816 self.context, fake_share_network, fake_sec_service, 

6817 current_security_service=None) 

6818 mock_get_key.assert_not_called() 

6819 

6820 def test_update_share_network_security_service_without_check(self): 

6821 mock_initial_checks = self.mock_object( 

6822 self.api, '_share_network_update_initial_checks', 

6823 mock.Mock(return_value=(['fake_server'], ['fake_host']))) 

6824 mock_get_key = self.mock_object( 

6825 self.api, 'get_security_service_update_key', 

6826 mock.Mock(return_value=None)) 

6827 fake_share_network = {'id': 'fake_share_net_id'} 

6828 fake_sec_service = {'id': 'fake_sec_serv_id'} 

6829 

6830 self.assertRaises(exception.InvalidShareNetwork, 

6831 self.api.update_share_network_security_service, 

6832 self.context, fake_share_network, fake_sec_service) 

6833 

6834 mock_initial_checks.assert_called_once_with( 

6835 self.context, fake_share_network, fake_sec_service, 

6836 current_security_service=None) 

6837 mock_get_key.assert_called_once_with( 

6838 'hosts_check', fake_sec_service['id'], 

6839 current_security_service_id=None) 

6840 

6841 def test_update_share_network_security_service_update_hosts_failure(self): 

6842 mock_initial_checks = self.mock_object( 

6843 self.api, '_share_network_update_initial_checks', 

6844 mock.Mock(return_value=(['fake_server'], ['fake_host']))) 

6845 mock_get_key = self.mock_object( 

6846 self.api, 'get_security_service_update_key', 

6847 mock.Mock(return_value='fake_key')) 

6848 mock_async_db_get = self.mock_object( 

6849 db_api, 'async_operation_data_get', 

6850 mock.Mock(return_value='fake_value')) 

6851 mock_validate_host = self.mock_object( 

6852 self.api, '_security_service_update_validate_hosts', 

6853 mock.Mock(side_effect=Exception)) 

6854 mock_async_db_delete = self.mock_object( 

6855 db_api, 'async_operation_data_delete') 

6856 fake_share_network = {'id': 'fake_share_net_id'} 

6857 fake_sec_service = {'id': 'fake_sec_serv_id'} 

6858 

6859 self.assertRaises(exception.InvalidShareNetwork, 

6860 self.api.update_share_network_security_service, 

6861 self.context, fake_share_network, fake_sec_service) 

6862 

6863 mock_initial_checks.assert_called_once_with( 

6864 self.context, fake_share_network, fake_sec_service, 

6865 current_security_service=None) 

6866 mock_get_key.assert_called_once_with( 

6867 'hosts_check', fake_sec_service['id'], 

6868 current_security_service_id=None) 

6869 mock_async_db_get.assert_called_once_with( 

6870 self.context, fake_share_network['id'], 'fake_key') 

6871 mock_validate_host.assert_called_once_with( 

6872 self.context, fake_share_network, ['fake_host'], ['fake_server'], 

6873 new_security_service_id=fake_sec_service['id'], 

6874 current_security_service_id=None) 

6875 mock_async_db_delete.assert_called_once_with( 

6876 self.context, fake_share_network['id'], 'fake_key') 

6877 

6878 def test_update_share_network_security_service_backend_host_failure(self): 

6879 share_network = db_utils.create_share_network() 

6880 security_service = db_utils.create_security_service() 

6881 backend_host = 'fakehost' 

6882 

6883 mock_initial_checks = self.mock_object( 

6884 self.api, '_share_network_update_initial_checks', 

6885 mock.Mock(return_value=(['fake_server'], [backend_host]))) 

6886 mock_get_update_key = self.mock_object( 

6887 self.api, 'get_security_service_update_key', 

6888 mock.Mock(return_value='fake_key')) 

6889 mock_db_async_op = self.mock_object( 

6890 db_api, 'async_operation_data_get', 

6891 mock.Mock(return_value='fake_update_value')) 

6892 mock_validate_host = self.mock_object( 

6893 self.api, '_security_service_update_validate_hosts', 

6894 mock.Mock(return_value=(False, None))) 

6895 

6896 self.assertRaises( 

6897 exception.InvalidShareNetwork, 

6898 self.api.update_share_network_security_service, 

6899 self.context, share_network, security_service) 

6900 

6901 mock_initial_checks.assert_called_once_with( 

6902 self.context, share_network, security_service, 

6903 current_security_service=None) 

6904 mock_db_async_op.assert_called_once_with( 

6905 self.context, share_network['id'], 'fake_key') 

6906 mock_get_update_key.assert_called_once_with( 

6907 'hosts_check', security_service['id'], 

6908 current_security_service_id=None) 

6909 mock_validate_host.assert_called_once_with( 

6910 self.context, share_network, [backend_host], ['fake_server'], 

6911 new_security_service_id=security_service['id'], 

6912 current_security_service_id=None) 

6913 

6914 def test_update_share_network_security_service(self): 

6915 share_network = db_utils.create_share_network() 

6916 security_service = db_utils.create_security_service() 

6917 backend_hosts = ['fakehost'] 

6918 fake_update_key = 'fake_key' 

6919 servers = [ 

6920 db_utils.create_share_server() for i in range(2)] 

6921 server_ids = [server['id'] for server in servers] 

6922 

6923 mock_initial_checks = self.mock_object( 

6924 self.api, '_share_network_update_initial_checks', 

6925 mock.Mock(return_value=(servers, backend_hosts))) 

6926 mock_get_update_key = self.mock_object( 

6927 self.api, 'get_security_service_update_key', 

6928 mock.Mock(return_value=fake_update_key)) 

6929 mock_db_async_op = self.mock_object( 

6930 db_api, 'async_operation_data_get', 

6931 mock.Mock(return_value='fake_update_value')) 

6932 mock_validate_host = self.mock_object( 

6933 self.api, '_security_service_update_validate_hosts', 

6934 mock.Mock(return_value=(True, None))) 

6935 mock_network_update = self.mock_object( 

6936 db_api, 'share_network_update') 

6937 mock_servers_update = self.mock_object( 

6938 db_api, 'share_servers_update') 

6939 mock_update_security_services = self.mock_object( 

6940 self.share_rpcapi, 'update_share_network_security_service') 

6941 mock_db_async_op_del = self.mock_object( 

6942 db_api, 'async_operation_data_delete',) 

6943 

6944 self.api.update_share_network_security_service( 

6945 self.context, share_network, security_service) 

6946 

6947 mock_initial_checks.assert_called_once_with( 

6948 self.context, share_network, security_service, 

6949 current_security_service=None) 

6950 mock_db_async_op.assert_called_once_with( 

6951 self.context, share_network['id'], fake_update_key) 

6952 mock_get_update_key.assert_called_once_with( 

6953 'hosts_check', security_service['id'], 

6954 current_security_service_id=None) 

6955 mock_validate_host.assert_called_once_with( 

6956 self.context, share_network, backend_hosts, servers, 

6957 new_security_service_id=security_service['id'], 

6958 current_security_service_id=None) 

6959 mock_network_update.assert_called_once_with( 

6960 self.context, share_network['id'], 

6961 {'status': constants.STATUS_NETWORK_CHANGE}) 

6962 mock_servers_update.assert_called_once_with( 

6963 self.context, server_ids, 

6964 {'status': constants.STATUS_SERVER_NETWORK_CHANGE} 

6965 ) 

6966 mock_update_security_services.assert_called_once_with( 

6967 self.context, backend_hosts[0], share_network['id'], 

6968 security_service['id'], current_security_service_id=None) 

6969 mock_db_async_op_del.assert_called_once_with( 

6970 self.context, share_network['id'], fake_update_key) 

6971 

6972 def test__security_service_update_validate_hosts_new_check(self): 

6973 curr_sec_service_id = "fake_curr_sec_serv_id" 

6974 new_sec_service_id = "fake_new_sec_serv_id" 

6975 fake_key = (curr_sec_service_id + '_' + new_sec_service_id + 

6976 '_' + 'hosts_check') 

6977 fake_share_network = {'id': 'fake_network_id'} 

6978 backend_hosts = {'hostA', 'hostB'} 

6979 fake_return = 'fake_update' 

6980 mock_get_key = self.mock_object( 

6981 self.api, 'get_security_service_update_key', 

6982 mock.Mock(return_value=fake_key)) 

6983 mock_do_update_validate = self.mock_object( 

6984 self.api, '_do_update_validate_hosts', 

6985 mock.Mock(return_value=fake_return)) 

6986 

6987 res = self.api._security_service_update_validate_hosts( 

6988 self.context, fake_share_network, backend_hosts, None, 

6989 new_security_service_id=new_sec_service_id, 

6990 current_security_service_id=curr_sec_service_id) 

6991 

6992 self.assertEqual(fake_return, res) 

6993 mock_get_key.assert_called_once_with( 

6994 'hosts_check', new_sec_service_id, 

6995 current_security_service_id=curr_sec_service_id) 

6996 mock_do_update_validate.assert_called_once_with( 

6997 self.context, fake_share_network['id'], backend_hosts, fake_key, 

6998 new_security_service_id=new_sec_service_id, 

6999 current_security_service_id=curr_sec_service_id) 

7000 

7001 @ddt.data(True, False) 

7002 def test__do_update_validate_hosts(self, update_security_service): 

7003 curr_sec_service_id = None 

7004 new_sec_service_id = None 

7005 new_share_network_subnet = 'fake_new_share_network_subnet' 

7006 if update_security_service: 

7007 curr_sec_service_id = "fake_curr_sec_serv_id" 

7008 new_sec_service_id = "fake_new_sec_serv_id" 

7009 new_share_network_subnet = None 

7010 

7011 fake_key = 'fake_key' 

7012 fake_share_network_id = 'fake_network_id' 

7013 backend_hosts = {'hostA', 'hostB'} 

7014 hosts_to_validate = {} 

7015 for bh in backend_hosts: 

7016 hosts_to_validate[bh] = None 

7017 mock_async_data_get = self.mock_object( 

7018 db_api, 'async_operation_data_get', mock.Mock(return_value=None)) 

7019 mock_async_data_update = self.mock_object( 

7020 db_api, 'async_operation_data_update') 

7021 mock_check_update_allocations = self.mock_object( 

7022 self.share_rpcapi, 'check_update_share_server_network_allocations') 

7023 mock_check_update_services = self.mock_object( 

7024 self.share_rpcapi, 'check_update_share_network_security_service') 

7025 

7026 compatible, hosts_info = self.api._do_update_validate_hosts( 

7027 self.context, fake_share_network_id, backend_hosts, fake_key, 

7028 new_share_network_subnet=new_share_network_subnet, 

7029 new_security_service_id=new_sec_service_id, 

7030 current_security_service_id=curr_sec_service_id) 

7031 

7032 self.assertIsNone(compatible) 

7033 self.assertEqual(hosts_to_validate, hosts_info) 

7034 mock_async_data_get.assert_called_once_with( 

7035 self.context, fake_share_network_id, fake_key) 

7036 mock_async_data_update.assert_called_once_with( 

7037 self.context, fake_share_network_id, 

7038 {fake_key: json.dumps(hosts_to_validate)}) 

7039 mock_share_api_check_calls = [] 

7040 for host in backend_hosts: 

7041 if update_security_service: 

7042 mock_share_api_check_calls.append( 

7043 mock.call(self.context, host, fake_share_network_id, 

7044 new_sec_service_id, 

7045 current_security_service_id=curr_sec_service_id)) 

7046 else: 

7047 mock_share_api_check_calls.append( 

7048 mock.call(self.context, host, fake_share_network_id, 

7049 new_share_network_subnet)) 

7050 if update_security_service: 

7051 mock_check_update_services.assert_has_calls( 

7052 mock_share_api_check_calls) 

7053 mock_check_update_allocations.assert_not_called() 

7054 else: 

7055 mock_check_update_allocations.assert_has_calls( 

7056 mock_share_api_check_calls) 

7057 mock_check_update_services.assert_not_called() 

7058 

7059 @ddt.data( 

7060 {'update_security_service': True, 'new_host': None, 

7061 'host_support': None, 'exp_result': None}, 

7062 {'update_security_service': True, 'new_host': None, 

7063 'host_support': False, 'exp_result': False}, 

7064 {'update_security_service': True, 'new_host': None, 

7065 'host_support': True, 'exp_result': True}, 

7066 {'update_security_service': True, 'new_host': 'hostC', 

7067 'host_support': None, 'exp_result': None}, 

7068 {'update_security_service': True, 'new_host': 'hostC', 

7069 'host_support': False, 'exp_result': False}, 

7070 {'update_security_service': True, 'new_host': 'hostC', 

7071 'host_support': True, 'exp_result': None}, 

7072 {'update_security_service': False, 'new_host': None, 

7073 'host_support': None, 'exp_result': None}, 

7074 {'update_security_service': False, 'new_host': None, 

7075 'host_support': False, 'exp_result': False}, 

7076 {'update_security_service': False, 'new_host': None, 

7077 'host_support': True, 'exp_result': True}, 

7078 {'update_security_service': False, 'new_host': 'hostC', 

7079 'host_support': None, 'exp_result': None}, 

7080 {'update_security_service': False, 'new_host': 'hostC', 

7081 'host_support': False, 'exp_result': False}, 

7082 {'update_security_service': False, 'new_host': 'hostC', 

7083 'host_support': True, 'exp_result': None}, 

7084 ) 

7085 @ddt.unpack 

7086 def test__do_update_validate_hosts_all( 

7087 self, update_security_service, new_host, host_support, exp_result): 

7088 curr_sec_service_id = None 

7089 new_sec_service_id = None 

7090 new_share_network_subnet = 'fake_new_share_network_subnet' 

7091 if update_security_service: 

7092 curr_sec_service_id = "fake_curr_sec_serv_id" 

7093 new_sec_service_id = "fake_new_sec_serv_id" 

7094 new_share_network_subnet = None 

7095 

7096 fake_key = 'fake_key' 

7097 fake_share_network_id = 'fake_network_id' 

7098 backend_hosts = ['hostA', 'hostB'] 

7099 hosts_to_validate = {} 

7100 for bh in backend_hosts: 

7101 hosts_to_validate[bh] = host_support 

7102 json_orig_hosts = json.dumps(hosts_to_validate) 

7103 

7104 if new_host: 

7105 backend_hosts.append(new_host) 

7106 hosts_to_validate[new_host] = None 

7107 

7108 mock_async_data_get = self.mock_object( 

7109 db_api, 'async_operation_data_get', 

7110 mock.Mock(return_value=json_orig_hosts)) 

7111 mock_async_data_update = self.mock_object( 

7112 db_api, 'async_operation_data_update') 

7113 mock_check_update_allocations = self.mock_object( 

7114 self.share_rpcapi, 'check_update_share_server_network_allocations') 

7115 mock_check_update_services = self.mock_object( 

7116 self.share_rpcapi, 'check_update_share_network_security_service') 

7117 

7118 result, hosts_info = self.api._do_update_validate_hosts( 

7119 self.context, fake_share_network_id, backend_hosts, fake_key, 

7120 new_share_network_subnet=new_share_network_subnet, 

7121 new_security_service_id=new_sec_service_id, 

7122 current_security_service_id=curr_sec_service_id) 

7123 

7124 self.assertEqual(exp_result, result) 

7125 self.assertEqual(hosts_to_validate, hosts_info) 

7126 mock_async_data_get.assert_called_once_with( 

7127 self.context, fake_share_network_id, fake_key) 

7128 

7129 # we fail earlier if one one the host answer False. 

7130 if new_host and host_support is not False: 

7131 mock_async_data_update.assert_called_once_with( 

7132 self.context, fake_share_network_id, 

7133 {fake_key: json.dumps(hosts_to_validate)}) 

7134 if update_security_service: 

7135 mock_check_update_services.assert_called_once_with( 

7136 self.context, new_host, fake_share_network_id, 

7137 new_sec_service_id, 

7138 current_security_service_id=curr_sec_service_id) 

7139 else: 

7140 mock_check_update_allocations.assert_called_once_with( 

7141 self.context, new_host, fake_share_network_id, 

7142 new_share_network_subnet) 

7143 

7144 def test_soft_delete_share_already_soft_deleted(self): 

7145 share = fakes.fake_share(id='fake_id', 

7146 status=constants.STATUS_AVAILABLE, 

7147 is_soft_deleted=True) 

7148 self.assertRaises(exception.InvalidShare, 

7149 self.api.soft_delete, self.context, share) 

7150 

7151 def test_soft_delete_invalid_status(self): 

7152 invalid_status = 'fake' 

7153 share = fakes.fake_share(id='fake_id', 

7154 status=invalid_status, 

7155 is_soft_deleted=False) 

7156 

7157 self.assertRaises(exception.InvalidShare, 

7158 self.api.soft_delete, self.context, share) 

7159 

7160 def test_soft_delete_share_with_replicas(self): 

7161 share = fakes.fake_share(id='fake_id', 

7162 has_replicas=True, 

7163 status=constants.STATUS_AVAILABLE, 

7164 is_soft_deleted=False) 

7165 

7166 self.assertRaises(exception.Conflict, 

7167 self.api.soft_delete, self.context, share) 

7168 

7169 def test_soft_delete_share_with_snapshot(self): 

7170 share = fakes.fake_share(id='fake_id', 

7171 status=constants.STATUS_AVAILABLE, 

7172 has_replicas=False, 

7173 is_soft_deleted=False) 

7174 snapshot = fakes.fake_snapshot(create_instance=True, as_primitive=True) 

7175 mock_db_snapshot_call = self.mock_object( 

7176 db_api, 'share_snapshot_get_all_for_share', mock.Mock( 

7177 return_value=[snapshot])) 

7178 

7179 self.assertRaises(exception.InvalidShare, 

7180 self.api.soft_delete, self.context, share) 

7181 

7182 mock_db_snapshot_call.assert_called_once_with( 

7183 self.context, share['id']) 

7184 

7185 @mock.patch.object(db_api, 'count_share_group_snapshot_members_in_share', 

7186 mock.Mock(return_value=2)) 

7187 def test_soft_delete_share_with_group_snapshot_members(self): 

7188 share = fakes.fake_share(id='fake_id', 

7189 status=constants.STATUS_AVAILABLE, 

7190 has_replicas=False, 

7191 is_soft_deleted=False) 

7192 self.mock_object(db_api, 'share_backups_get_all', 

7193 mock.Mock(return_value=[])) 

7194 

7195 self.assertRaises(exception.InvalidShare, 

7196 self.api.soft_delete, self.context, share) 

7197 

7198 def test_soft_delete_locked_share(self): 

7199 self.mock_object( 

7200 self.api.db, 

7201 'resource_lock_get_all', 

7202 mock.Mock(return_value=([{'id': 'l1'}, {'id': 'l2'}], None)) 

7203 ) 

7204 share = self._setup_delete_mocks('available') 

7205 self.mock_object(db_api, 'share_soft_delete') 

7206 

7207 self.assertRaises(exception.InvalidShare, 

7208 self.api.soft_delete, 

7209 self.context, 

7210 share) 

7211 

7212 # lock check decorator executed first, nothing else is invoked 

7213 db_api.share_soft_delete.assert_not_called() 

7214 db_api.share_snapshot_get_all_for_share.assert_not_called() 

7215 

7216 def test_soft_delete_share(self): 

7217 share = fakes.fake_share(id='fake_id', 

7218 status=constants.STATUS_AVAILABLE, 

7219 has_replicas=False, 

7220 is_soft_deleted=False) 

7221 self.mock_object(db_api, 'share_snapshot_get_all_for_share', 

7222 mock.Mock(return_value=[])) 

7223 self.mock_object(db_api, 'share_backups_get_all', 

7224 mock.Mock(return_value=[])) 

7225 self.mock_object(db_api, 'count_share_group_snapshot_members_in_share', 

7226 mock.Mock(return_value=0)) 

7227 self.mock_object(db_api, 'share_soft_delete') 

7228 self.mock_object(self.api, '_check_is_share_busy') 

7229 self.api.soft_delete(self.context, share) 

7230 self.api._check_is_share_busy.assert_called_once_with(share) 

7231 

7232 def test_restore_share(self): 

7233 share = fakes.fake_share(id='fake_id', 

7234 status=constants.STATUS_AVAILABLE, 

7235 is_soft_deleted=True) 

7236 self.mock_object(db_api, 'share_restore') 

7237 self.api.restore(self.context, share) 

7238 

7239 def test__share_server_update_allocations_validate_hosts(self): 

7240 update_return = 'fake_return' 

7241 mock_do_update = self.mock_object( 

7242 self.api, '_do_update_validate_hosts', 

7243 mock.Mock(return_value=update_return)) 

7244 

7245 backend_hosts = 'fake_hosts' 

7246 update_key = 'fake_key' 

7247 share_network_id = 'fake_net_id' 

7248 subnet = { 

7249 'neutron_net_id': 'fake_net_id', 

7250 'neutron_subnet_id': 'fake_subnet_id', 

7251 'availability_zone_id': 'fake_availability_zone_id', 

7252 } 

7253 res = self.api._share_server_update_allocations_validate_hosts( 

7254 self.context, backend_hosts, update_key, 

7255 share_network_id=share_network_id, 

7256 neutron_net_id=subnet['neutron_net_id'], 

7257 neutron_subnet_id=subnet['neutron_subnet_id'], 

7258 availability_zone_id=subnet['availability_zone_id']) 

7259 

7260 self.assertEqual(update_return, res) 

7261 mock_do_update.assert_called_once_with( 

7262 self.context, share_network_id, backend_hosts, update_key, 

7263 new_share_network_subnet=subnet) 

7264 

7265 def test_get_share_server_update_allocations_key(self): 

7266 availability_zone_id = None 

7267 share_network_id = 'fake_share_network_id' 

7268 expected_key = ('share_server_update_allocations_' + 

7269 share_network_id + '_' + str(availability_zone_id) + 

7270 '_' + 'hosts_check') 

7271 res = self.api.get_share_server_update_allocations_key( 

7272 share_network_id, availability_zone_id) 

7273 

7274 self.assertEqual(expected_key, res) 

7275 

7276 def test__share_server_update_allocations_initial_checks(self): 

7277 share_network = db_utils.create_share_network() 

7278 share1 = db_utils.create_share( 

7279 share_network_id=share_network['id'], 

7280 status=constants.STATUS_AVAILABLE) 

7281 server_host = 'fake_host' 

7282 share_server = db_utils.create_share_server(host=server_host) 

7283 mock_validate_service_host = self.mock_object( 

7284 utils, 'validate_service_host') 

7285 mock_share_get_all_by_share_server = self.mock_object( 

7286 self.api.db, 'share_get_all_by_share_server', 

7287 mock.Mock(return_value=[share1])) 

7288 mock_share_is_busy = self.mock_object( 

7289 self.api, '_check_is_share_busy') 

7290 

7291 res_hosts = self.api._share_server_update_allocations_initial_checks( 

7292 self.context, share_network, [share_server]) 

7293 

7294 self.assertEqual(set([server_host]), res_hosts) 

7295 mock_validate_service_host.assert_called_once() 

7296 mock_share_get_all_by_share_server.assert_called_once_with( 

7297 self.context, share_server['id']) 

7298 mock_share_is_busy.assert_called_once_with(share1) 

7299 

7300 def test__share_server_update_allocations_initial_checks_no_support(self): 

7301 fake_share_network = { 

7302 'id': 'fake_sn_id', 

7303 'network_allocation_update_support': False, 

7304 'status': constants.STATUS_NETWORK_ACTIVE, 

7305 } 

7306 sn_subnet = db_utils.create_share_network_subnet() 

7307 

7308 self.assertRaises( 

7309 exception.InvalidShareNetwork, 

7310 self.api._share_server_update_allocations_initial_checks, 

7311 self.context, 

7312 fake_share_network, 

7313 sn_subnet) 

7314 

7315 def test__share_server_update_allocations_initial_checks_inactive(self): 

7316 share_network = db_utils.create_share_network() 

7317 share_server = db_utils.create_share_server( 

7318 status=constants.STATUS_INACTIVE) 

7319 

7320 self.assertRaises( 

7321 exception.InvalidShareNetwork, 

7322 self.api._share_server_update_allocations_initial_checks, 

7323 self.context, 

7324 share_network, 

7325 [share_server]) 

7326 

7327 def test__share_server_update_allocations_initial_checks_shares_na(self): 

7328 share_network = db_utils.create_share_network() 

7329 share1 = db_utils.create_share( 

7330 share_network_id=share_network['id'], 

7331 status=constants.STATUS_ERROR) 

7332 share_server = db_utils.create_share_server() 

7333 mock_validate_service_host = self.mock_object( 

7334 utils, 'validate_service_host') 

7335 mock_share_get_all_by_share_server = self.mock_object( 

7336 self.api.db, 'share_get_all_by_share_server', 

7337 mock.Mock(return_value=[share1])) 

7338 

7339 self.assertRaises( 

7340 exception.InvalidShareNetwork, 

7341 self.api._share_server_update_allocations_initial_checks, 

7342 self.context, 

7343 share_network, 

7344 [share_server]) 

7345 

7346 mock_validate_service_host.assert_called_once() 

7347 mock_share_get_all_by_share_server.assert_called_once_with( 

7348 self.context, share_server['id']) 

7349 

7350 def test__share_server_update_allocations_initial_checks_rules_na(self): 

7351 share_network = db_utils.create_share_network() 

7352 share1 = db_utils.create_share( 

7353 share_network_id=share_network['id'], 

7354 status=constants.STATUS_AVAILABLE) 

7355 share_server = db_utils.create_share_server() 

7356 share1['instance']['access_rules_status'] = constants.STATUS_INACTIVE 

7357 mock_validate_service_host = self.mock_object( 

7358 utils, 'validate_service_host') 

7359 mock_share_get_all_by_share_server = self.mock_object( 

7360 self.api.db, 'share_get_all_by_share_server', 

7361 mock.Mock(return_value=[share1])) 

7362 

7363 self.assertRaises( 

7364 exception.InvalidShareNetwork, 

7365 self.api._share_server_update_allocations_initial_checks, 

7366 self.context, 

7367 share_network, 

7368 [share_server]) 

7369 

7370 mock_validate_service_host.assert_called_once() 

7371 mock_share_get_all_by_share_server.assert_called_once_with( 

7372 self.context, share_server['id']) 

7373 

7374 def test__share_server_update_allocations_initial_checks_share_busy(self): 

7375 share_network = db_utils.create_share_network() 

7376 share1 = db_utils.create_share( 

7377 share_network_id=share_network['id'], 

7378 status=constants.STATUS_AVAILABLE) 

7379 share_server = db_utils.create_share_server() 

7380 mock_validate_service_host = self.mock_object( 

7381 utils, 'validate_service_host') 

7382 mock_share_get_all_by_share_server = self.mock_object( 

7383 self.api.db, 'share_get_all_by_share_server', 

7384 mock.Mock(return_value=[share1])) 

7385 mock_share_is_busy = self.mock_object( 

7386 self.api, '_check_is_share_busy', 

7387 mock.Mock(side_effect=exception.ShareBusyException(message='fake')) 

7388 ) 

7389 

7390 self.assertRaises( 

7391 exception.InvalidShareNetwork, 

7392 self.api._share_server_update_allocations_initial_checks, 

7393 self.context, 

7394 share_network, 

7395 [share_server]) 

7396 

7397 mock_validate_service_host.assert_called_once() 

7398 mock_share_get_all_by_share_server.assert_called_once_with( 

7399 self.context, share_server['id']) 

7400 mock_share_is_busy.assert_called_once_with(share1) 

7401 

7402 def test_check_update_share_server_network_allocations(self): 

7403 backend_hosts = 'fake_hosts' 

7404 mock_initial_check = self.mock_object( 

7405 self.api, '_share_server_update_allocations_initial_checks', 

7406 mock.Mock(return_value=backend_hosts)) 

7407 update_key = 'fake_key' 

7408 mock_get_key = self.mock_object( 

7409 self.api, 'get_share_server_update_allocations_key', 

7410 mock.Mock(return_value=update_key)) 

7411 mock_reset_data = self.mock_object( 

7412 self.api.db, 'async_operation_data_delete') 

7413 compatible = True 

7414 hosts_info = {'fake_host': True} 

7415 mock_validate_hosts = self.mock_object( 

7416 self.api, '_share_server_update_allocations_validate_hosts', 

7417 mock.Mock(return_value=(compatible, hosts_info))) 

7418 

7419 share_network = {'id': 'fake_id'} 

7420 new_share_network_subnet = { 

7421 'share_servers': 'fake_servers', 

7422 'availability_zone_id': 'fake_availability_zone_id', 

7423 'neutron_net_id': 'fake_neutron_net_id', 

7424 'neutron_subnet_id': 'fake_neutron_subnet_id', 

7425 } 

7426 res = self.api.check_update_share_server_network_allocations( 

7427 self.context, share_network, new_share_network_subnet, True) 

7428 

7429 self.assertEqual( 

7430 {'compatible': compatible, 'hosts_check_result': hosts_info}, res) 

7431 mock_initial_check.assert_called_once_with( 

7432 self.context, share_network, 

7433 new_share_network_subnet['share_servers']) 

7434 mock_get_key.assert_called_once_with( 

7435 share_network['id'], 

7436 new_share_network_subnet['availability_zone_id']) 

7437 mock_reset_data.assert_called_once_with( 

7438 self.context, share_network['id'], update_key) 

7439 mock_validate_hosts.assert_called_once_with( 

7440 self.context, backend_hosts, update_key, 

7441 share_network_id=share_network['id'], 

7442 neutron_net_id=new_share_network_subnet['neutron_net_id'], 

7443 neutron_subnet_id=new_share_network_subnet['neutron_subnet_id'], 

7444 availability_zone_id=( 

7445 new_share_network_subnet["availability_zone_id"])) 

7446 

7447 def test_check_update_share_server_network_allocations_failed(self): 

7448 backend_hosts = 'fake_hosts' 

7449 self.mock_object( 

7450 self.api, '_share_server_update_allocations_initial_checks', 

7451 mock.Mock(return_value=backend_hosts)) 

7452 update_key = 'fake_key' 

7453 self.mock_object( 

7454 self.api, 'get_share_server_update_allocations_key', 

7455 mock.Mock(return_value=update_key)) 

7456 self.mock_object(self.api.db, 'async_operation_data_delete') 

7457 self.mock_object( 

7458 self.api, '_share_server_update_allocations_validate_hosts', 

7459 mock.Mock(side_effect=exception.InvalidShareNetwork(reason="msg"))) 

7460 

7461 share_network = {'id': 'fake_id'} 

7462 new_share_network_subnet = { 

7463 'share_servers': 'fake_servers', 

7464 'availability_zone_id': 'fake_availability_zone_id', 

7465 'neutron_net_id': 'fake_neutron_net_id', 

7466 'neutron_subnet_id': 'fake_neutron_subnet_id', 

7467 } 

7468 self.assertRaises( 

7469 exception.InvalidShareNetwork, 

7470 self.api.check_update_share_server_network_allocations, 

7471 self.context, share_network, new_share_network_subnet, True) 

7472 

7473 def test_update_share_server_network_allocations(self): 

7474 backend_host = 'fake_host' 

7475 backend_hosts = [backend_host] 

7476 mock_initial_check = self.mock_object( 

7477 self.api, '_share_server_update_allocations_initial_checks', 

7478 mock.Mock(return_value=backend_hosts)) 

7479 update_key = 'fake_key' 

7480 mock_get_key = self.mock_object( 

7481 self.api, 'get_share_server_update_allocations_key', 

7482 mock.Mock(return_value=update_key)) 

7483 mock_get_data = self.mock_object( 

7484 self.api.db, 'async_operation_data_get', 

7485 mock.Mock(return_value='fake_update_value')) 

7486 mock_validate_hosts = self.mock_object( 

7487 self.api, '_share_server_update_allocations_validate_hosts', 

7488 mock.Mock(return_value=(True, 'fake_host'))) 

7489 mock_net_update = self.mock_object(self.api.db, 'share_network_update') 

7490 mock_server_update = self.mock_object(self.api.db, 

7491 'share_servers_update') 

7492 new_share_network_subnet_db = {'id': 'fake_subnet_id'} 

7493 mock_subnet_create = self.mock_object( 

7494 self.api.db, 'share_network_subnet_create', 

7495 mock.Mock(return_value=new_share_network_subnet_db)) 

7496 mock_update_allocations = self.mock_object( 

7497 self.api.share_rpcapi, 'update_share_server_network_allocations') 

7498 mock_delete_data = self.mock_object(self.api.db, 

7499 'async_operation_data_delete') 

7500 

7501 share_network = {'id': 'fake_id'} 

7502 server1 = {'id': 'fake_id'} 

7503 new_share_network_subnet = { 

7504 'share_servers': [server1], 

7505 'availability_zone_id': 'fake_availability_zone_id', 

7506 'neutron_net_id': 'fake_neutron_net_id', 

7507 'neutron_subnet_id': 'fake_neutron_subnet_id', 

7508 } 

7509 res_subnet = self.api.update_share_server_network_allocations( 

7510 self.context, share_network, new_share_network_subnet) 

7511 

7512 self.assertEqual(new_share_network_subnet_db, res_subnet) 

7513 mock_initial_check.assert_called_once_with( 

7514 self.context, share_network, 

7515 new_share_network_subnet['share_servers']) 

7516 mock_get_key.assert_called_once_with( 

7517 share_network['id'], 

7518 new_share_network_subnet['availability_zone_id']) 

7519 mock_get_data.assert_called_once_with( 

7520 self.context, share_network['id'], update_key) 

7521 mock_validate_hosts.assert_called_once_with( 

7522 self.context, backend_hosts, update_key, 

7523 share_network_id=share_network['id'], 

7524 neutron_net_id=new_share_network_subnet['neutron_net_id'], 

7525 neutron_subnet_id=new_share_network_subnet['neutron_subnet_id'], 

7526 availability_zone_id=( 

7527 new_share_network_subnet["availability_zone_id"])) 

7528 mock_net_update.assert_called_once_with( 

7529 self.context, share_network['id'], 

7530 {'status': constants.STATUS_NETWORK_CHANGE}) 

7531 mock_server_update.assert_called_once_with( 

7532 self.context, [server1['id']], 

7533 {'status': constants.STATUS_SERVER_NETWORK_CHANGE}) 

7534 mock_subnet_create.assert_called_once_with( 

7535 self.context, new_share_network_subnet) 

7536 mock_update_allocations.assert_called_once_with( 

7537 self.context, backend_host, share_network['id'], 

7538 new_share_network_subnet_db['id']) 

7539 mock_delete_data.assert_called_once_with( 

7540 self.context, share_network['id'], update_key) 

7541 

7542 def test_update_share_server_network_allocations_no_check(self): 

7543 backend_host = 'fake_host' 

7544 backend_hosts = [backend_host] 

7545 self.mock_object( 

7546 self.api, '_share_server_update_allocations_initial_checks', 

7547 mock.Mock(return_value=backend_hosts)) 

7548 update_key = 'fake_key' 

7549 self.mock_object( 

7550 self.api, 'get_share_server_update_allocations_key', 

7551 mock.Mock(return_value=update_key)) 

7552 self.mock_object( 

7553 self.api.db, 'async_operation_data_get', 

7554 mock.Mock(return_value=None)) 

7555 

7556 share_network = {'id': 'fake_id'} 

7557 server1 = {'id': 'fake_id'} 

7558 new_share_network_subnet = { 

7559 'share_servers': [server1], 

7560 'availability_zone_id': 'fake_availability_zone_id', 

7561 'neutron_net_id': 'fake_neutron_net_id', 

7562 'neutron_subnet_id': 'fake_neutron_subnet_id', 

7563 } 

7564 self.assertRaises( 

7565 exception.InvalidShareNetwork, 

7566 self.api.update_share_server_network_allocations, 

7567 self.context, 

7568 share_network, 

7569 new_share_network_subnet) 

7570 

7571 def test_update_share_server_network_allocations_fail_validation(self): 

7572 backend_host = 'fake_host' 

7573 backend_hosts = [backend_host] 

7574 self.mock_object( 

7575 self.api, '_share_server_update_allocations_initial_checks', 

7576 mock.Mock(return_value=backend_hosts)) 

7577 update_key = 'fake_key' 

7578 self.mock_object( 

7579 self.api, 'get_share_server_update_allocations_key', 

7580 mock.Mock(return_value=update_key)) 

7581 self.mock_object( 

7582 self.api.db, 'async_operation_data_get', 

7583 mock.Mock(return_value='fake_update_value')) 

7584 self.mock_object( 

7585 self.api, '_share_server_update_allocations_validate_hosts', 

7586 mock.Mock(side_effect=exception.InvalidShareNetwork( 

7587 reason='fake_reason'))) 

7588 mock_delete_data = self.mock_object(self.api.db, 

7589 'async_operation_data_delete') 

7590 

7591 share_network = {'id': 'fake_id'} 

7592 server1 = {'id': 'fake_id'} 

7593 new_share_network_subnet = { 

7594 'share_servers': [server1], 

7595 'availability_zone_id': 'fake_availability_zone_id', 

7596 'neutron_net_id': 'fake_neutron_net_id', 

7597 'neutron_subnet_id': 'fake_neutron_subnet_id', 

7598 } 

7599 self.assertRaises( 

7600 exception.InvalidShareNetwork, 

7601 self.api.update_share_server_network_allocations, 

7602 self.context, 

7603 share_network, 

7604 new_share_network_subnet) 

7605 

7606 mock_delete_data.assert_called_once_with( 

7607 self.context, share_network['id'], update_key) 

7608 

7609 @ddt.data(False, None) 

7610 def test_update_share_server_network_allocations_check_fail(self, result): 

7611 backend_host = 'fake_host' 

7612 backend_hosts = [backend_host] 

7613 self.mock_object( 

7614 self.api, '_share_server_update_allocations_initial_checks', 

7615 mock.Mock(return_value=backend_hosts)) 

7616 update_key = 'fake_key' 

7617 self.mock_object( 

7618 self.api, 'get_share_server_update_allocations_key', 

7619 mock.Mock(return_value=update_key)) 

7620 self.mock_object( 

7621 self.api.db, 'async_operation_data_get', 

7622 mock.Mock(return_value='fake_update_value')) 

7623 self.mock_object( 

7624 self.api, '_share_server_update_allocations_validate_hosts', 

7625 mock.Mock(return_value=(result, 'fake_host'))) 

7626 

7627 share_network = {'id': 'fake_id'} 

7628 server1 = {'id': 'fake_id'} 

7629 new_share_network_subnet = { 

7630 'share_servers': [server1], 

7631 'availability_zone_id': 'fake_availability_zone_id', 

7632 'neutron_net_id': 'fake_neutron_net_id', 

7633 'neutron_subnet_id': 'fake_neutron_subnet_id', 

7634 } 

7635 self.assertRaises( 

7636 exception.InvalidShareNetwork, 

7637 self.api.update_share_server_network_allocations, 

7638 self.context, 

7639 share_network, 

7640 new_share_network_subnet) 

7641 

7642 @ddt.data(None, {'driver': test}) 

7643 def test_create_share_backup(self, backup_opts): 

7644 share = db_utils.create_share(is_public=True, status='available') 

7645 backup_ref = db_utils.create_backup(share['id'], status='available') 

7646 

7647 reservation = 'fake' 

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

7649 mock.Mock(return_value=reservation)) 

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

7651 self.mock_object(db_api, 'share_backup_create', 

7652 mock.Mock(return_value=backup_ref)) 

7653 self.mock_object(db_api, 'share_backup_update', mock.Mock()) 

7654 self.mock_object(data_rpc.DataAPI, 'create_backup', mock.Mock()) 

7655 self.mock_object(self.share_rpcapi, 'create_backup', mock.Mock()) 

7656 

7657 backup = { 

7658 'display_name': 'tmp_backup', 

7659 'backup_options': backup_opts, 

7660 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7661 } 

7662 self.api.create_share_backup(self.context, share, backup) 

7663 

7664 quota.QUOTAS.reserve.assert_called_once() 

7665 db_api.share_backup_create.assert_called_once() 

7666 quota.QUOTAS.commit.assert_called_once() 

7667 db_api.share_backup_update.assert_called_once() 

7668 if backup_opts: 

7669 self.share_rpcapi.create_backup.assert_called_once_with( 

7670 self.context, backup_ref) 

7671 else: 

7672 data_rpc.DataAPI.create_backup.assert_called_once_with( 

7673 self.context, backup_ref) 

7674 

7675 @ddt.data('CEPHFS', 'CIFS') 

7676 def test_create_generic_share_backup_invalid_protocol(self, share_proto): 

7677 CONF.set_default( 

7678 "data_manager_backup_supported_share_protocols", ["MANGO"]) 

7679 share = db_utils.create_share( 

7680 is_public=True, status='available', share_proto=share_proto) 

7681 backup_ref = db_utils.create_backup(share['id'], status='available') 

7682 

7683 reservation = 'fake' 

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

7685 mock.Mock(return_value=reservation)) 

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

7687 self.mock_object(quota.QUOTAS, 'rollback') 

7688 self.mock_object(db_api, 'share_backup_create', 

7689 mock.Mock(return_value=backup_ref)) 

7690 self.mock_object(data_rpc.DataAPI, 'create_backup', mock.Mock()) 

7691 

7692 backup = { 

7693 'display_name': 'tmp_backup', 

7694 'backup_options': {}, 

7695 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7696 } 

7697 self.assertRaises( 

7698 exception.InvalidShare, 

7699 self.api.create_share_backup, 

7700 self.context, 

7701 share, 

7702 backup, 

7703 ) 

7704 

7705 quota.QUOTAS.reserve.assert_called_once_with( 

7706 self.context, backups=1, backup_gigabytes=share['size'] 

7707 ) 

7708 db_api.share_backup_create.assert_not_called() 

7709 quota.QUOTAS.rollback.assert_called_once_with( 

7710 self.context, reservation) 

7711 quota.QUOTAS.commit.assert_not_called() 

7712 data_rpc.DataAPI.create_backup.assert_not_called() 

7713 

7714 def test_create_share_backup_share_error_state(self): 

7715 share = db_utils.create_share(is_public=True, status='error') 

7716 backup = { 

7717 'display_name': 'tmp_backup', 

7718 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7719 } 

7720 self.assertRaises(exception.InvalidShare, 

7721 self.api.create_share_backup, 

7722 self.context, share, backup) 

7723 

7724 def test_create_share_backup_share_busy_task_state(self): 

7725 share = db_utils.create_share( 

7726 is_public=True, task_state='data_copying_in_progress') 

7727 backup = { 

7728 'display_name': 'tmp_backup', 

7729 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7730 } 

7731 

7732 self.assertRaises(exception.ShareBusyException, 

7733 self.api.create_share_backup, 

7734 self.context, share, backup) 

7735 

7736 def test_create_share_backup_share_has_snapshots(self): 

7737 share = db_utils.create_share( 

7738 is_public=True, state='available') 

7739 snapshot = db_utils.create_snapshot( 

7740 share_id=share['id'], status='available', size=1) 

7741 

7742 backup = { 

7743 'display_name': 'tmp_backup', 

7744 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7745 } 

7746 

7747 self.mock_object(db_api, 'share_snapshot_get_all_for_share', 

7748 mock.Mock(return_value=[snapshot])) 

7749 

7750 self.assertRaises(exception.InvalidShare, 

7751 self.api.create_share_backup, 

7752 self.context, share, backup) 

7753 

7754 def test_create_share_backup_share_has_replicas(self): 

7755 share = fakes.fake_share(id='fake_id', 

7756 has_replicas=True, 

7757 status=constants.STATUS_AVAILABLE, 

7758 is_soft_deleted=False) 

7759 backup = { 

7760 'display_name': 'tmp_backup', 

7761 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7762 } 

7763 

7764 self.assertRaises(exception.InvalidShare, 

7765 self.api.create_share_backup, 

7766 self.context, share, backup) 

7767 

7768 @ddt.data({'overs': {'backup_gigabytes': 'fake'}, 

7769 'expected_exception': 

7770 exception.ShareBackupSizeExceedsAvailableQuota}, 

7771 {'overs': {'backups': 'fake'}, 

7772 'expected_exception': exception.BackupLimitExceeded},) 

7773 @ddt.unpack 

7774 def test_create_share_backup_over_quota(self, overs, expected_exception): 

7775 share = fakes.fake_share(id='fake_id', 

7776 status=constants.STATUS_AVAILABLE, 

7777 is_soft_deleted=False, size=5) 

7778 backup = { 

7779 'display_name': 'tmp_backup', 

7780 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7781 } 

7782 

7783 usages = {'backup_gigabytes': {'reserved': 5, 'in_use': 5}, 

7784 'backups': {'reserved': 5, 'in_use': 5}} 

7785 

7786 quotas = {'backup_gigabytes': 5, 'backups': 5} 

7787 

7788 exc = exception.OverQuota(overs=overs, usages=usages, quotas=quotas) 

7789 self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc)) 

7790 

7791 self.assertRaises(expected_exception, self.api.create_share_backup, 

7792 self.context, share, backup) 

7793 

7794 quota.QUOTAS.reserve.assert_called_once_with( 

7795 self.context, backups=1, backup_gigabytes=share['size']) 

7796 

7797 def test_create_share_backup_rollback_quota(self): 

7798 share = db_utils.create_share(is_public=True, status='available') 

7799 

7800 reservation = 'fake' 

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

7802 mock.Mock(return_value=reservation)) 

7803 self.mock_object(quota.QUOTAS, 'rollback') 

7804 self.mock_object(db_api, 'share_backup_create', 

7805 mock.Mock(side_effect=exception.ManilaException)) 

7806 self.mock_object(data_rpc.DataAPI, 'create_backup', mock.Mock()) 

7807 self.mock_object(self.share_rpcapi, 'create_backup', mock.Mock()) 

7808 

7809 backup = { 

7810 'display_name': 'tmp_backup', 

7811 'id': 'dbe28dff-ce7d-4c3d-a795-c31f6fee31ab', 

7812 } 

7813 self.assertRaises(exception.ManilaException, 

7814 self.api.create_share_backup, 

7815 self.context, share, backup) 

7816 

7817 quota.QUOTAS.reserve.assert_called_once() 

7818 db_api.share_backup_create.assert_called_once() 

7819 quota.QUOTAS.rollback.assert_called_once_with( 

7820 self.context, reservation) 

7821 

7822 @ddt.data(CONF.share_topic, CONF.data_topic) 

7823 def test_delete_share_backup(self, topic): 

7824 share = db_utils.create_share(is_public=True, status='available') 

7825 backup = db_utils.create_backup(share['id'], status='available') 

7826 

7827 self.mock_object(db_api, 'share_backup_update', mock.Mock()) 

7828 self.mock_object(data_rpc.DataAPI, 'delete_backup', mock.Mock()) 

7829 self.mock_object(self.share_rpcapi, 'delete_backup', mock.Mock()) 

7830 

7831 backup.update({'topic': topic}) 

7832 self.api.delete_share_backup(self.context, backup) 

7833 

7834 db_api.share_backup_update.assert_called_once() 

7835 if topic == CONF.share_topic: 

7836 self.share_rpcapi.delete_backup.assert_called_once_with( 

7837 self.context, backup) 

7838 else: 

7839 data_rpc.DataAPI.delete_backup.assert_called_once_with( 

7840 self.context, backup) 

7841 

7842 @ddt.data(constants.STATUS_DELETING, constants.STATUS_CREATING) 

7843 def test_delete_share_backup_invalid_state(self, state): 

7844 share = db_utils.create_share(is_public=True, status='available') 

7845 backup = db_utils.create_backup(share['id'], status=state) 

7846 self.assertRaises(exception.InvalidBackup, 

7847 self.api.delete_share_backup, 

7848 self.context, backup) 

7849 

7850 @ddt.data(CONF.share_topic, CONF.data_topic) 

7851 def test_restore_share_backup(self, topic): 

7852 share = db_utils.create_share( 

7853 is_public=True, status='available', size=1) 

7854 backup = db_utils.create_backup( 

7855 share['id'], status='available', size=1) 

7856 

7857 self.mock_object(self.api, 'get', mock.Mock(return_value=share)) 

7858 self.mock_object(db_api, 'share_backup_update', mock.Mock()) 

7859 self.mock_object(db_api, 'share_update', mock.Mock()) 

7860 self.mock_object(data_rpc.DataAPI, 'restore_backup', mock.Mock()) 

7861 self.mock_object(self.share_rpcapi, 'restore_backup', mock.Mock()) 

7862 

7863 backup.update({'topic': topic}) 

7864 self.api.restore_share_backup(self.context, backup) 

7865 

7866 self.api.get.assert_called_once() 

7867 db_api.share_update.assert_called_once() 

7868 db_api.share_backup_update.assert_called_once() 

7869 if topic == CONF.share_topic: 

7870 self.share_rpcapi.restore_backup.assert_called_once_with( 

7871 self.context, backup, share['id']) 

7872 else: 

7873 data_rpc.DataAPI.restore_backup.assert_called_once_with( 

7874 self.context, backup, share['id']) 

7875 

7876 def test_restore_share_backup_invalid_share_sizee(self): 

7877 share = db_utils.create_share( 

7878 is_public=True, status='available', size=1) 

7879 backup = db_utils.create_backup( 

7880 share['id'], status='available', size=2) 

7881 self.assertRaises(exception.InvalidShare, 

7882 self.api.restore_share_backup, 

7883 self.context, backup) 

7884 

7885 def test_restore_share_backup_invalid_share_state(self): 

7886 share = db_utils.create_share(is_public=True, status='deleting') 

7887 backup = db_utils.create_backup(share['id'], status='available') 

7888 self.assertRaises(exception.InvalidShare, 

7889 self.api.restore_share_backup, 

7890 self.context, backup) 

7891 

7892 def test_restore_share_backup_invalid_backup_state(self): 

7893 share = db_utils.create_share(is_public=True, status='available') 

7894 backup = db_utils.create_backup(share['id'], status='deleting') 

7895 self.assertRaises(exception.InvalidBackup, 

7896 self.api.restore_share_backup, 

7897 self.context, backup) 

7898 

7899 def test_update_share_backup(self): 

7900 share = db_utils.create_share(is_public=True, status='available') 

7901 backup = db_utils.create_backup(share['id'], status='available') 

7902 self.mock_object(db_api, 'share_backup_update', mock.Mock()) 

7903 

7904 self.api.update_share_backup(self.context, backup, 

7905 {'display_name': 'new_name'}) 

7906 

7907 db_api.share_backup_update.assert_called_once() 

7908 

7909 

7910class OtherTenantsShareActionsTestCase(test.TestCase): 

7911 def setUp(self): 

7912 super(OtherTenantsShareActionsTestCase, self).setUp() 

7913 self.api = share.API() 

7914 

7915 def test_delete_other_tenants_public_share(self): 

7916 share = db_utils.create_share(is_public=True) 

7917 ctx = context.RequestContext(user_id='1111', project_id='2222') 

7918 self.assertRaises(exception.PolicyNotAuthorized, self.api.delete, ctx, 

7919 share) 

7920 

7921 def test_update_other_tenants_public_share(self): 

7922 share = db_utils.create_share(is_public=True) 

7923 ctx = context.RequestContext(user_id='1111', project_id='2222') 

7924 self.assertRaises(exception.PolicyNotAuthorized, self.api.update, ctx, 

7925 share, {'display_name': 'newname'}) 

7926 

7927 def test_get_other_tenants_public_share(self): 

7928 share = db_utils.create_share(is_public=True) 

7929 ctx = context.RequestContext(user_id='1111', project_id='2222') 

7930 self.mock_object(db_api, 'share_get', 

7931 mock.Mock(return_value=share)) 

7932 result = self.api.get(ctx, 'fakeid') 

7933 self.assertEqual(share, result) 

7934 db_api.share_get.assert_called_once_with(ctx, 'fakeid')