Coverage for manila/tests/scheduler/test_host_manager.py: 99%

299 statements  

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

1# Copyright (c) 2011 OpenStack, LLC 

2# Copyright (c) 2015 Rushil Chugh 

3# Copyright (c) 2015 Clinton Knight 

4# All Rights Reserved. 

5# 

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

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

8# a copy of the License at 

9# 

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

11# 

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

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

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

15# License for the specific language governing permissions and limitations 

16# under the License. 

17""" 

18Tests For HostManager 

19""" 

20 

21import copy 

22from unittest import mock 

23 

24import ddt 

25from oslo_config import cfg 

26from oslo_utils import timeutils 

27 

28from manila import context 

29from manila import db 

30from manila import exception 

31from manila.scheduler.filters import base_host 

32from manila.scheduler import host_manager 

33from manila.scheduler import utils as scheduler_utils 

34from manila import test 

35from manila.tests.scheduler import fakes 

36from manila import utils 

37 

38 

39CONF = cfg.CONF 

40 

41 

42class FakeFilterClass1(base_host.BaseHostFilter): 

43 def host_passes(self, host_state, filter_properties): 

44 pass 

45 

46 

47class FakeFilterClass2(base_host.BaseHostFilter): 

48 def host_passes(self, host_state, filter_properties): 

49 pass 

50 

51 

52@ddt.ddt 

53class HostManagerTestCase(test.TestCase): 

54 """Test case for HostManager class.""" 

55 

56 def setUp(self): 

57 super(HostManagerTestCase, self).setUp() 

58 self.host_manager = host_manager.HostManager() 

59 self.fake_hosts = [host_manager.HostState('fake_host%s' % x) 

60 for x in range(1, 5)] 

61 

62 def test_choose_host_filters_not_found(self): 

63 self.flags(scheduler_default_filters='FakeFilterClass3') 

64 self.host_manager.filter_classes = [FakeFilterClass1, 

65 FakeFilterClass2] 

66 self.assertRaises(exception.SchedulerHostFilterNotFound, 

67 self.host_manager._choose_host_filters, None) 

68 

69 def test_choose_host_filters(self): 

70 self.flags(scheduler_default_filters=['FakeFilterClass2']) 

71 self.host_manager.filter_classes = [FakeFilterClass1, 

72 FakeFilterClass2] 

73 

74 # Test 'share' returns 1 correct function 

75 filter_classes = self.host_manager._choose_host_filters(None) 

76 self.assertEqual(1, len(filter_classes)) 

77 self.assertEqual('FakeFilterClass2', filter_classes[0].__name__) 

78 

79 def _verify_result(self, info, result): 

80 for x in info['got_fprops']: 

81 self.assertEqual(info['expected_fprops'], x) 

82 self.assertEqual(set(info['expected_objs']), set(info['got_objs'])) 

83 self.assertEqual(set(info['got_objs']), set(result)) 

84 

85 def test_get_filtered_hosts(self): 

86 fake_properties = {'moo': 1, 'cow': 2} 

87 info = { 

88 'expected_objs': self.fake_hosts, 

89 'expected_fprops': fake_properties, 

90 } 

91 with mock.patch.object(self.host_manager, '_choose_host_filters', 

92 mock.Mock(return_value=[FakeFilterClass1])): 

93 info['got_objs'] = [] 

94 info['got_fprops'] = [] 

95 

96 def fake_filter_one(_self, obj, filter_props): 

97 info['got_objs'].append(obj) 

98 info['got_fprops'].append(filter_props) 

99 return True 

100 

101 self.mock_object(FakeFilterClass1, '_filter_one', fake_filter_one) 

102 result, last_filter = self.host_manager.get_filtered_hosts( 

103 self.fake_hosts, fake_properties) 

104 self._verify_result(info, result) 

105 self.host_manager._choose_host_filters.assert_called_once_with( 

106 mock.ANY) 

107 

108 def test_update_service_capabilities_for_shares(self): 

109 service_states = self.host_manager.service_states 

110 self.assertDictEqual(service_states, {}) 

111 host1_share_capabs = dict(free_capacity_gb=4321, timestamp=1) 

112 host2_share_capabs = dict(free_capacity_gb=5432, timestamp=1) 

113 host3_share_capabs = dict(free_capacity_gb=6543, timestamp=1) 

114 service_name = 'share' 

115 self.host_manager.update_service_capabilities( 

116 service_name, 'host1', host1_share_capabs, 31337) 

117 

118 self.host_manager.update_service_capabilities( 

119 service_name, 'host2', host2_share_capabs, 31338) 

120 

121 self.host_manager.update_service_capabilities( 

122 service_name, 'host3', host3_share_capabs, 31339) 

123 

124 # Make sure dictionary isn't re-assigned 

125 self.assertEqual(service_states, self.host_manager.service_states) 

126 # Make sure original dictionary wasn't copied 

127 self.assertEqual(1, host1_share_capabs['timestamp']) 

128 

129 host1_share_capabs['timestamp'] = 31337 

130 host2_share_capabs['timestamp'] = 31338 

131 host3_share_capabs['timestamp'] = 31339 

132 

133 expected = { 

134 'host1': host1_share_capabs, 

135 'host2': host2_share_capabs, 

136 'host3': host3_share_capabs, 

137 } 

138 self.assertDictEqual(service_states, expected) 

139 

140 def test_get_all_host_states_share(self): 

141 fake_context = context.RequestContext('user', 'project') 

142 topic = CONF.share_topic 

143 tmp_pools = copy.deepcopy(fakes.SHARE_SERVICES_WITH_POOLS) 

144 tmp_enable_pools = tmp_pools[:-2] 

145 self.mock_object( 

146 db, 'service_get_all_by_topic', 

147 mock.Mock(return_value=tmp_enable_pools)) 

148 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

149 

150 with mock.patch.dict(self.host_manager.service_states, 

151 fakes.SHARE_SERVICE_STATES_WITH_POOLS): 

152 # Get service 

153 self.host_manager.get_all_host_states_share(fake_context) 

154 

155 # Disabled one service 

156 tmp_enable_pools.pop() 

157 self.mock_object( 

158 db, 'service_get_all_by_topic', 

159 mock.Mock(return_value=tmp_enable_pools)) 

160 

161 # Get service again 

162 self.host_manager.get_all_host_states_share(fake_context) 

163 host_state_map = self.host_manager.host_state_map 

164 

165 self.assertEqual(3, len(host_state_map)) 

166 # Check that service is up 

167 for i in range(3): 

168 share_node = fakes.SHARE_SERVICES_WITH_POOLS[i] 

169 host = share_node['host'] 

170 self.assertEqual(share_node, host_state_map[host].service) 

171 db.service_get_all_by_topic.assert_called_once_with( 

172 fake_context, topic, consider_disabled=False) 

173 

174 def test_get_pools_no_pools(self): 

175 fake_context = context.RequestContext('user', 'project') 

176 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

177 self.mock_object( 

178 db, 'service_get_all_by_topic', 

179 mock.Mock(return_value=fakes.SHARE_SERVICES_NO_POOLS)) 

180 host_manager.LOG.warning = mock.Mock() 

181 

182 with mock.patch.dict(self.host_manager.service_states, 

183 fakes.SERVICE_STATES_NO_POOLS): 

184 

185 res = self.host_manager.get_pools(context=fake_context) 

186 

187 expected = [ 

188 { 

189 'name': 'host1#AAA', 

190 'host': 'host1', 

191 'backend': None, 

192 'pool': 'AAA', 

193 'capabilities': { 

194 'timestamp': None, 

195 'share_backend_name': 'AAA', 

196 'free_capacity_gb': 200, 

197 'driver_version': None, 

198 'total_capacity_gb': 512, 

199 'reserved_percentage': 0, 

200 'reserved_snapshot_percentage': 0, 

201 'reserved_share_extend_percentage': 0, 

202 'provisioned_capacity_gb': 312, 

203 'max_over_subscription_ratio': 1.0, 

204 'thin_provisioning': False, 

205 'vendor_name': None, 

206 'storage_protocol': None, 

207 'driver_handles_share_servers': False, 

208 'snapshot_support': False, 

209 'create_share_from_snapshot_support': False, 

210 'revert_to_snapshot_support': True, 

211 'mount_snapshot_support': True, 

212 'dedupe': False, 

213 'compression': False, 

214 'replication_type': None, 

215 'replication_domain': None, 

216 'sg_consistent_snapshot_support': None, 

217 'security_service_update_support': False, 

218 'network_allocation_update_support': False, 

219 'share_server_multiple_subnet_support': False, 

220 'mount_point_name_support': False, 

221 'share_replicas_migration_support': False, 

222 'encryption_support': None 

223 }, 

224 }, { 

225 'name': 'host2@back1#BBB', 

226 'host': 'host2', 

227 'backend': 'back1', 

228 'pool': 'BBB', 

229 'capabilities': { 

230 'timestamp': None, 

231 'share_backend_name': 'BBB', 

232 'free_capacity_gb': 100, 

233 'driver_version': None, 

234 'total_capacity_gb': 256, 

235 'reserved_percentage': 0, 

236 'reserved_snapshot_percentage': 0, 

237 'reserved_share_extend_percentage': 0, 

238 'provisioned_capacity_gb': 400, 

239 'max_over_subscription_ratio': 2.0, 

240 'thin_provisioning': True, 

241 'vendor_name': None, 

242 'storage_protocol': None, 

243 'driver_handles_share_servers': False, 

244 'snapshot_support': True, 

245 'create_share_from_snapshot_support': True, 

246 'revert_to_snapshot_support': False, 

247 'mount_snapshot_support': False, 

248 'dedupe': False, 

249 'compression': False, 

250 'replication_type': None, 

251 'replication_domain': None, 

252 'sg_consistent_snapshot_support': None, 

253 'security_service_update_support': False, 

254 'network_allocation_update_support': False, 

255 'share_server_multiple_subnet_support': False, 

256 'mount_point_name_support': False, 

257 'share_replicas_migration_support': False, 

258 'encryption_support': None 

259 }, 

260 }, { 

261 'name': 'host2@back2#CCC', 

262 'host': 'host2', 

263 'backend': 'back2', 

264 'pool': 'CCC', 

265 'capabilities': { 

266 'timestamp': None, 

267 'share_backend_name': 'CCC', 

268 'free_capacity_gb': 700, 

269 'driver_version': None, 

270 'total_capacity_gb': 10000, 

271 'reserved_percentage': 0, 

272 'reserved_snapshot_percentage': 0, 

273 'reserved_share_extend_percentage': 0, 

274 'provisioned_capacity_gb': 50000, 

275 'max_over_subscription_ratio': 20.0, 

276 'thin_provisioning': True, 

277 'vendor_name': None, 

278 'storage_protocol': None, 

279 'driver_handles_share_servers': False, 

280 'snapshot_support': True, 

281 'create_share_from_snapshot_support': True, 

282 'revert_to_snapshot_support': False, 

283 'mount_snapshot_support': False, 

284 'dedupe': False, 

285 'compression': False, 

286 'replication_type': None, 

287 'replication_domain': None, 

288 'sg_consistent_snapshot_support': None, 

289 'security_service_update_support': False, 

290 'network_allocation_update_support': False, 

291 'share_server_multiple_subnet_support': False, 

292 'mount_point_name_support': False, 

293 'share_replicas_migration_support': False, 

294 'encryption_support': None 

295 }, 

296 }, 

297 ] 

298 self.assertIsInstance(res, list) 

299 self.assertEqual(len(expected), len(res)) 

300 for pool in expected: 

301 self.assertIn(pool, res) 

302 

303 def test_get_pools(self): 

304 fake_context = context.RequestContext('user', 'project') 

305 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

306 self.mock_object( 

307 db, 'service_get_all_by_topic', 

308 mock.Mock(return_value=fakes.SHARE_SERVICES_WITH_POOLS)) 

309 host_manager.LOG.warning = mock.Mock() 

310 

311 with mock.patch.dict(self.host_manager.service_states, 

312 fakes.SHARE_SERVICE_STATES_WITH_POOLS): 

313 

314 res = self.host_manager.get_pools(fake_context) 

315 

316 expected = [ 

317 { 

318 'name': 'host1@AAA#pool1', 

319 'host': 'host1', 

320 'backend': 'AAA', 

321 'pool': 'pool1', 

322 'capabilities': { 

323 'pool_name': 'pool1', 

324 'timestamp': None, 

325 'share_backend_name': 'AAA', 

326 'free_capacity_gb': 41, 

327 'driver_version': None, 

328 'total_capacity_gb': 51, 

329 'reserved_percentage': 0, 

330 'reserved_snapshot_percentage': 0, 

331 'reserved_share_extend_percentage': 0, 

332 'provisioned_capacity_gb': 10, 

333 'max_over_subscription_ratio': 1.0, 

334 'thin_provisioning': False, 

335 'vendor_name': None, 

336 'storage_protocol': None, 

337 'driver_handles_share_servers': False, 

338 'snapshot_support': True, 

339 'create_share_from_snapshot_support': True, 

340 'revert_to_snapshot_support': True, 

341 'mount_snapshot_support': False, 

342 'dedupe': False, 

343 'compression': False, 

344 'replication_type': None, 

345 'replication_domain': None, 

346 'sg_consistent_snapshot_support': None, 

347 'security_service_update_support': False, 

348 'network_allocation_update_support': False, 

349 'share_server_multiple_subnet_support': False, 

350 'mount_point_name_support': False, 

351 'share_replicas_migration_support': False, 

352 'encryption_support': None 

353 }, 

354 }, { 

355 'name': 'host2@BBB#pool2', 

356 'host': 'host2', 

357 'backend': 'BBB', 

358 'pool': 'pool2', 

359 'capabilities': { 

360 'pool_name': 'pool2', 

361 'timestamp': None, 

362 'share_backend_name': 'BBB', 

363 'free_capacity_gb': 42, 

364 'driver_version': None, 

365 'total_capacity_gb': 52, 

366 'reserved_percentage': 0, 

367 'reserved_snapshot_percentage': 0, 

368 'reserved_share_extend_percentage': 0, 

369 'provisioned_capacity_gb': 60, 

370 'max_over_subscription_ratio': 2.0, 

371 'thin_provisioning': True, 

372 'vendor_name': None, 

373 'storage_protocol': None, 

374 'driver_handles_share_servers': False, 

375 'snapshot_support': True, 

376 'create_share_from_snapshot_support': True, 

377 'revert_to_snapshot_support': False, 

378 'mount_snapshot_support': False, 

379 'dedupe': False, 

380 'compression': False, 

381 'replication_type': None, 

382 'replication_domain': None, 

383 'sg_consistent_snapshot_support': None, 

384 'security_service_update_support': False, 

385 'network_allocation_update_support': False, 

386 'share_server_multiple_subnet_support': False, 

387 'mount_point_name_support': False, 

388 'share_replicas_migration_support': False, 

389 'encryption_support': None 

390 }, 

391 }, { 

392 'name': 'host3@CCC#pool3', 

393 'host': 'host3', 

394 'backend': 'CCC', 

395 'pool': 'pool3', 

396 'capabilities': { 

397 'pool_name': 'pool3', 

398 'timestamp': None, 

399 'share_backend_name': 'CCC', 

400 'free_capacity_gb': 43, 

401 'driver_version': None, 

402 'total_capacity_gb': 53, 

403 'reserved_percentage': 0, 

404 'reserved_snapshot_percentage': 0, 

405 'reserved_share_extend_percentage': 0, 

406 'provisioned_capacity_gb': 100, 

407 'max_over_subscription_ratio': 20.0, 

408 'thin_provisioning': True, 

409 'vendor_name': None, 

410 'storage_protocol': None, 

411 'driver_handles_share_servers': False, 

412 'snapshot_support': True, 

413 'create_share_from_snapshot_support': True, 

414 'revert_to_snapshot_support': False, 

415 'mount_snapshot_support': False, 

416 'dedupe': False, 

417 'compression': False, 

418 'replication_type': None, 

419 'replication_domain': None, 

420 'sg_consistent_snapshot_support': None, 

421 'security_service_update_support': False, 

422 'network_allocation_update_support': False, 

423 'share_server_multiple_subnet_support': False, 

424 'mount_point_name_support': False, 

425 'share_replicas_migration_support': False, 

426 'encryption_support': None 

427 }, 

428 }, { 

429 'name': 'host4@DDD#pool4a', 

430 'host': 'host4', 

431 'backend': 'DDD', 

432 'pool': 'pool4a', 

433 'capabilities': { 

434 'pool_name': 'pool4a', 

435 'timestamp': None, 

436 'share_backend_name': 'DDD', 

437 'free_capacity_gb': 441, 

438 'driver_version': None, 

439 'total_capacity_gb': 541, 

440 'reserved_percentage': 0, 

441 'reserved_snapshot_percentage': 0, 

442 'reserved_share_extend_percentage': 0, 

443 'provisioned_capacity_gb': 800, 

444 'max_over_subscription_ratio': 2.0, 

445 'thin_provisioning': True, 

446 'vendor_name': None, 

447 'storage_protocol': None, 

448 'driver_handles_share_servers': False, 

449 'snapshot_support': True, 

450 'create_share_from_snapshot_support': True, 

451 'revert_to_snapshot_support': False, 

452 'mount_snapshot_support': False, 

453 'dedupe': False, 

454 'compression': False, 

455 'replication_type': None, 

456 'replication_domain': None, 

457 'sg_consistent_snapshot_support': None, 

458 'security_service_update_support': False, 

459 'network_allocation_update_support': False, 

460 'share_server_multiple_subnet_support': False, 

461 'mount_point_name_support': False, 

462 'share_replicas_migration_support': False, 

463 'encryption_support': None 

464 }, 

465 }, { 

466 'name': 'host4@DDD#pool4b', 

467 'host': 'host4', 

468 'backend': 'DDD', 

469 'pool': 'pool4b', 

470 'capabilities': { 

471 'pool_name': 'pool4b', 

472 'timestamp': None, 

473 'share_backend_name': 'DDD', 

474 'free_capacity_gb': 442, 

475 'driver_version': None, 

476 'total_capacity_gb': 542, 

477 'reserved_percentage': 0, 

478 'reserved_snapshot_percentage': 0, 

479 'reserved_share_extend_percentage': 0, 

480 'provisioned_capacity_gb': 2000, 

481 'max_over_subscription_ratio': 10.0, 

482 'thin_provisioning': True, 

483 'vendor_name': None, 

484 'storage_protocol': None, 

485 'driver_handles_share_servers': False, 

486 'snapshot_support': True, 

487 'create_share_from_snapshot_support': True, 

488 'revert_to_snapshot_support': False, 

489 'mount_snapshot_support': False, 

490 'dedupe': False, 

491 'compression': False, 

492 'replication_type': None, 

493 'replication_domain': None, 

494 'sg_consistent_snapshot_support': None, 

495 'security_service_update_support': False, 

496 'network_allocation_update_support': False, 

497 'share_server_multiple_subnet_support': False, 

498 'mount_point_name_support': False, 

499 'share_replicas_migration_support': False, 

500 'encryption_support': None, 

501 }, 

502 }, 

503 ] 

504 self.assertIsInstance(res, list) 

505 self.assertIsInstance(self.host_manager.host_state_map, dict) 

506 self.assertEqual(len(expected), len(res)) 

507 for pool in expected: 

508 self.assertIn(pool, res) 

509 

510 def test_get_pools_host_down(self): 

511 fake_context = context.RequestContext('user', 'project') 

512 mock_service_is_up = self.mock_object(utils, 'service_is_up') 

513 self.mock_object( 

514 db, 'service_get_all_by_topic', 

515 mock.Mock(return_value=fakes.SHARE_SERVICES_NO_POOLS)) 

516 host_manager.LOG.warning = mock.Mock() 

517 

518 with mock.patch.dict(self.host_manager.service_states, 

519 fakes.SERVICE_STATES_NO_POOLS): 

520 

521 # Initialize host data with all services present 

522 mock_service_is_up.side_effect = [True, True, True] 

523 

524 # Call once to update the host state map 

525 self.host_manager.get_pools(fake_context) 

526 

527 self.assertEqual(len(fakes.SHARE_SERVICES_NO_POOLS), 

528 len(self.host_manager.host_state_map)) 

529 

530 # Then mock one host as down 

531 mock_service_is_up.side_effect = [True, True, False] 

532 

533 res = self.host_manager.get_pools(fake_context) 

534 

535 expected = [ 

536 { 

537 'name': 'host1#AAA', 

538 'host': 'host1', 

539 'backend': None, 

540 'pool': 'AAA', 

541 'capabilities': { 

542 'timestamp': None, 

543 'driver_handles_share_servers': False, 

544 'snapshot_support': False, 

545 'create_share_from_snapshot_support': False, 

546 'revert_to_snapshot_support': True, 

547 'mount_snapshot_support': True, 

548 'share_backend_name': 'AAA', 

549 'free_capacity_gb': 200, 

550 'driver_version': None, 

551 'total_capacity_gb': 512, 

552 'reserved_percentage': 0, 

553 'reserved_snapshot_percentage': 0, 

554 'reserved_share_extend_percentage': 0, 

555 'vendor_name': None, 

556 'storage_protocol': None, 

557 'provisioned_capacity_gb': 312, 

558 'max_over_subscription_ratio': 1.0, 

559 'thin_provisioning': False, 

560 'dedupe': False, 

561 'compression': False, 

562 'replication_type': None, 

563 'replication_domain': None, 

564 'sg_consistent_snapshot_support': None, 

565 'security_service_update_support': False, 

566 'network_allocation_update_support': False, 

567 'share_server_multiple_subnet_support': False, 

568 'mount_point_name_support': False, 

569 'share_replicas_migration_support': False, 

570 'encryption_support': None 

571 }, 

572 }, { 

573 'name': 'host2@back1#BBB', 

574 'host': 'host2', 

575 'backend': 'back1', 

576 'pool': 'BBB', 

577 'capabilities': { 

578 'timestamp': None, 

579 'driver_handles_share_servers': False, 

580 'snapshot_support': True, 

581 'create_share_from_snapshot_support': True, 

582 'revert_to_snapshot_support': False, 

583 'mount_snapshot_support': False, 

584 'share_backend_name': 'BBB', 

585 'free_capacity_gb': 100, 

586 'driver_version': None, 

587 'total_capacity_gb': 256, 

588 'reserved_percentage': 0, 

589 'reserved_snapshot_percentage': 0, 

590 'reserved_share_extend_percentage': 0, 

591 'vendor_name': None, 

592 'storage_protocol': None, 

593 'provisioned_capacity_gb': 400, 

594 'max_over_subscription_ratio': 2.0, 

595 'thin_provisioning': True, 

596 'dedupe': False, 

597 'compression': False, 

598 'replication_type': None, 

599 'replication_domain': None, 

600 'sg_consistent_snapshot_support': None, 

601 'security_service_update_support': False, 

602 'network_allocation_update_support': False, 

603 'share_server_multiple_subnet_support': False, 

604 'mount_point_name_support': False, 

605 'share_replicas_migration_support': False, 

606 'encryption_support': None 

607 }, 

608 }, 

609 ] 

610 self.assertIsInstance(res, list) 

611 self.assertIsInstance(self.host_manager.host_state_map, dict) 

612 self.assertEqual(len(expected), len(res)) 

613 self.assertEqual(len(expected), 

614 len(self.host_manager.host_state_map)) 

615 for pool in expected: 

616 self.assertIn(pool, res) 

617 

618 def test_get_pools_with_filters(self): 

619 fake_context = context.RequestContext('user', 'project') 

620 self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True)) 

621 self.mock_object( 

622 db, 'service_get_all_by_topic', 

623 mock.Mock(return_value=fakes.SHARE_SERVICES_WITH_POOLS)) 

624 host_manager.LOG.warning = mock.Mock() 

625 

626 with mock.patch.dict(self.host_manager.service_states, 

627 fakes.SHARE_SERVICE_STATES_WITH_POOLS): 

628 

629 res = self.host_manager.get_pools( 

630 context=fake_context, 

631 filters={'host': 'host2', 'pool': 'pool*', 

632 'capabilities': {'dedupe': 'False'}}) 

633 

634 expected = [ 

635 { 

636 'name': 'host2@BBB#pool2', 

637 'host': 'host2', 

638 'backend': 'BBB', 

639 'pool': 'pool2', 

640 'capabilities': { 

641 'pool_name': 'pool2', 

642 'timestamp': None, 

643 'driver_handles_share_servers': False, 

644 'snapshot_support': True, 

645 'create_share_from_snapshot_support': True, 

646 'revert_to_snapshot_support': False, 

647 'mount_snapshot_support': False, 

648 'share_backend_name': 'BBB', 

649 'free_capacity_gb': 42, 

650 'driver_version': None, 

651 'total_capacity_gb': 52, 

652 'reserved_percentage': 0, 

653 'reserved_snapshot_percentage': 0, 

654 'reserved_share_extend_percentage': 0, 

655 'provisioned_capacity_gb': 60, 

656 'max_over_subscription_ratio': 2.0, 

657 'thin_provisioning': True, 

658 'vendor_name': None, 

659 'storage_protocol': None, 

660 'dedupe': False, 

661 'compression': False, 

662 'replication_type': None, 

663 'replication_domain': None, 

664 'sg_consistent_snapshot_support': None, 

665 'security_service_update_support': False, 

666 'network_allocation_update_support': False, 

667 'share_server_multiple_subnet_support': False, 

668 'mount_point_name_support': False, 

669 'share_replicas_migration_support': False, 

670 'encryption_support': None 

671 }, 

672 }, 

673 ] 

674 self.assertIsInstance(res, list) 

675 self.assertEqual(len(expected), len(res)) 

676 for pool in expected: 

677 self.assertIn(pool, res) 

678 

679 @ddt.data( 

680 None, 

681 {}, 

682 {'key1': 'value1'}, 

683 {'capabilities': {'dedupe': 'False'}}, 

684 {'capabilities': {'dedupe': '<is> False'}}, 

685 {'key1': 'value1', 'key2': 'value*'}, 

686 {'key1': '.*', 'key2': '.*'}, 

687 ) 

688 def test_passes_filters_true(self, filter): 

689 

690 data = { 

691 'key1': 'value1', 

692 'key2': 'value2', 

693 'key3': 'value3', 

694 'capabilities': {'dedupe': False}, 

695 } 

696 self.assertTrue(self.host_manager._passes_filters(data, filter)) 

697 

698 @ddt.data( 

699 {'key1': 'value$'}, 

700 {'key4': 'value'}, 

701 {'capabilities': {'dedupe': 'True'}}, 

702 {'capabilities': {'dedupe': '<is> True'}}, 

703 {'key1': 'value1.+', 'key2': 'value*'}, 

704 ) 

705 def test_passes_filters_false(self, filter): 

706 

707 data = { 

708 'key1': 'value1', 

709 'key2': 'value2', 

710 'key3': 'value3', 

711 'capabilities': {'dedupe': False}, 

712 } 

713 self.assertFalse(self.host_manager._passes_filters(data, filter)) 

714 

715 

716class HostStateTestCase(test.TestCase): 

717 """Test case for HostState class.""" 

718 

719 def test_update_from_share_capability_nopool(self): 

720 fake_context = context.RequestContext('user', 'project', is_admin=True) 

721 share_capability = {'total_capacity_gb': 0, 

722 'free_capacity_gb': 100, 

723 'reserved_percentage': 0, 

724 'reserved_snapshot_percentage': 0, 

725 'reserved_share_extend_percentage': 0, 

726 'timestamp': None, 

727 'ipv4_support': True, 

728 'ipv6_support': False} 

729 fake_host = host_manager.HostState('host1', share_capability) 

730 self.assertIsNone(fake_host.free_capacity_gb) 

731 

732 fake_host.update_from_share_capability(share_capability, 

733 context=fake_context) 

734 # Backend level stats remain uninitialized 

735 self.assertEqual(0, fake_host.total_capacity_gb) 

736 self.assertIsNone(fake_host.free_capacity_gb) 

737 self.assertTrue(fake_host.ipv4_support) 

738 self.assertFalse(fake_host.ipv6_support) 

739 # Pool stats has been updated 

740 self.assertEqual(0, fake_host.pools['_pool0'].total_capacity_gb) 

741 self.assertEqual(100, fake_host.pools['_pool0'].free_capacity_gb) 

742 self.assertTrue(fake_host.pools['_pool0'].ipv4_support) 

743 self.assertFalse(fake_host.pools['_pool0'].ipv6_support) 

744 

745 # Test update for existing host state 

746 share_capability.update(dict(total_capacity_gb=1000)) 

747 fake_host.update_from_share_capability(share_capability, 

748 context=fake_context) 

749 self.assertEqual(1000, fake_host.pools['_pool0'].total_capacity_gb) 

750 

751 # Test update for existing host state with different backend name 

752 share_capability.update(dict(share_backend_name='magic')) 

753 fake_host.update_from_share_capability(share_capability, 

754 context=fake_context) 

755 self.assertEqual(1000, fake_host.pools['magic'].total_capacity_gb) 

756 self.assertEqual(100, fake_host.pools['magic'].free_capacity_gb) 

757 # 'pool0' becomes nonactive pool, and is deleted 

758 self.assertRaises(KeyError, lambda: fake_host.pools['pool0']) 

759 

760 def test_update_from_share_capability_with_pools(self): 

761 fake_context = context.RequestContext('user', 'project', is_admin=True) 

762 fake_host = host_manager.HostState('host1#pool1') 

763 self.assertIsNone(fake_host.free_capacity_gb) 

764 capability = { 

765 'share_backend_name': 'Backend1', 

766 'vendor_name': 'OpenStack', 

767 'driver_version': '1.1', 

768 'storage_protocol': 'NFS_CIFS', 

769 'ipv4_support': True, 

770 'ipv6_support': False, 

771 'pools': [ 

772 {'pool_name': 'pool1', 

773 'total_capacity_gb': 500, 

774 'free_capacity_gb': 230, 

775 'allocated_capacity_gb': 270, 

776 'qos': 'False', 

777 'reserved_percentage': 0, 

778 'reserved_snapshot_percentage': 0, 

779 'reserved_share_extend_percentage': 0, 

780 'dying_disks': 100, 

781 'super_hero_1': 'spider-man', 

782 'super_hero_2': 'flash', 

783 'super_hero_3': 'neoncat', 

784 }, 

785 {'pool_name': 'pool2', 

786 'total_capacity_gb': 1024, 

787 'free_capacity_gb': 1024, 

788 'allocated_capacity_gb': 0, 

789 'qos': 'False', 

790 'reserved_percentage': 0, 

791 'reserved_snapshot_percentage': 0, 

792 'reserved_share_extend_percentage': 0, 

793 'dying_disks': 200, 

794 'super_hero_1': 'superman', 

795 'super_hero_2': 'Hulk', 

796 } 

797 ], 

798 'timestamp': None, 

799 } 

800 

801 fake_host.update_from_share_capability(capability, 

802 context=fake_context) 

803 

804 self.assertEqual('Backend1', fake_host.share_backend_name) 

805 self.assertEqual('NFS_CIFS', fake_host.storage_protocol) 

806 self.assertEqual('OpenStack', fake_host.vendor_name) 

807 self.assertEqual('1.1', fake_host.driver_version) 

808 self.assertTrue(fake_host.ipv4_support) 

809 self.assertFalse(fake_host.ipv6_support) 

810 

811 # Backend level stats remain uninitialized 

812 self.assertEqual(0, fake_host.total_capacity_gb) 

813 self.assertIsNone(fake_host.free_capacity_gb) 

814 # Pool stats has been updated 

815 self.assertEqual(2, len(fake_host.pools)) 

816 

817 self.assertEqual(500, fake_host.pools['pool1'].total_capacity_gb) 

818 self.assertEqual(230, fake_host.pools['pool1'].free_capacity_gb) 

819 self.assertTrue(fake_host.pools['pool1'].ipv4_support) 

820 self.assertFalse(fake_host.pools['pool1'].ipv6_support) 

821 self.assertEqual(1024, fake_host.pools['pool2'].total_capacity_gb) 

822 self.assertEqual(1024, fake_host.pools['pool2'].free_capacity_gb) 

823 self.assertTrue(fake_host.pools['pool2'].ipv4_support) 

824 self.assertFalse(fake_host.pools['pool2'].ipv6_support) 

825 

826 capability = { 

827 'share_backend_name': 'Backend1', 

828 'vendor_name': 'OpenStack', 

829 'driver_version': '1.0', 

830 'storage_protocol': 'NFS_CIFS', 

831 'pools': [ 

832 {'pool_name': 'pool3', 

833 'total_capacity_gb': 10000, 

834 'free_capacity_gb': 10000, 

835 'allocated_capacity_gb': 0, 

836 'qos': 'False', 

837 'reserved_percentage': 0, 

838 'reserved_snapshot_percentage': 0, 

839 'reserved_share_extend_percentage': 0, 

840 }, 

841 ], 

842 'timestamp': None, 

843 } 

844 

845 # test update HostState Record 

846 fake_host.update_from_share_capability(capability, 

847 context=fake_context) 

848 

849 self.assertEqual('1.0', fake_host.driver_version) 

850 

851 # Non-active pool stats has been removed 

852 self.assertEqual(1, len(fake_host.pools)) 

853 

854 self.assertRaises(KeyError, lambda: fake_host.pools['pool1']) 

855 self.assertRaises(KeyError, lambda: fake_host.pools['pool2']) 

856 

857 self.assertEqual(10000, fake_host.pools['pool3'].total_capacity_gb) 

858 self.assertEqual(10000, fake_host.pools['pool3'].free_capacity_gb) 

859 

860 def test_update_from_share_unknown_capability(self): 

861 share_capability = { 

862 'total_capacity_gb': 'unknown', 

863 'free_capacity_gb': 'unknown', 

864 'allocated_capacity_gb': 1, 

865 'reserved_percentage': 0, 

866 'reserved_snapshot_percentage': 0, 

867 'reserved_share_extend_percentage': 0, 

868 'timestamp': None 

869 } 

870 fake_context = context.RequestContext('user', 'project', is_admin=True) 

871 fake_host = host_manager.HostState('host1#_pool0') 

872 self.assertIsNone(fake_host.free_capacity_gb) 

873 fake_host.update_from_share_capability(share_capability, 

874 context=fake_context) 

875 # Backend level stats remain uninitialized 

876 self.assertEqual(fake_host.total_capacity_gb, 0) 

877 self.assertIsNone(fake_host.free_capacity_gb) 

878 # Pool stats has been updated 

879 self.assertEqual(fake_host.pools['_pool0'].total_capacity_gb, 

880 'unknown') 

881 self.assertEqual(fake_host.pools['_pool0'].free_capacity_gb, 

882 'unknown') 

883 

884 def test_consume_from_share_capability(self): 

885 fake_context = context.RequestContext('user', 'project', is_admin=True) 

886 share_size = 10 

887 free_capacity = 100 

888 provisioned_capacity_gb = 50 

889 fake_share = {'id': 'foo', 'size': share_size} 

890 share_capability = { 

891 'total_capacity_gb': free_capacity * 2, 

892 'free_capacity_gb': free_capacity, 

893 'provisioned_capacity_gb': provisioned_capacity_gb, 

894 'allocated_capacity_gb': provisioned_capacity_gb, 

895 'reserved_percentage': 0, 

896 'reserved_snapshot_percentage': 0, 

897 'reserved_share_extend_percentage': 0, 

898 'timestamp': None 

899 } 

900 fake_host = host_manager.PoolState('host1', share_capability, '_pool0') 

901 

902 fake_host.update_from_share_capability(share_capability, 

903 context=fake_context) 

904 fake_host.consume_from_share(fake_share) 

905 self.assertEqual(fake_host.free_capacity_gb, 

906 free_capacity - share_size) 

907 self.assertEqual(fake_host.provisioned_capacity_gb, 

908 provisioned_capacity_gb + share_size) 

909 self.assertEqual(fake_host.allocated_capacity_gb, 

910 provisioned_capacity_gb + share_size) 

911 

912 def test_consume_from_share_unknown_capability(self): 

913 share_capability = { 

914 'total_capacity_gb': 'unknown', 

915 'free_capacity_gb': 'unknown', 

916 'provisioned_capacity_gb': None, 

917 'allocated_capacity_gb': 0, 

918 'reserved_percentage': 0, 

919 'reserved_snapshot_percentage': 0, 

920 'reserved_share_extend_percentage': 0, 

921 'timestamp': None 

922 } 

923 fake_context = context.RequestContext('user', 'project', is_admin=True) 

924 fake_host = host_manager.PoolState('host1', share_capability, '_pool0') 

925 share_size = 1000 

926 fake_share = {'id': 'foo', 'size': share_size} 

927 

928 fake_host.update_from_share_capability(share_capability, 

929 context=fake_context) 

930 fake_host.consume_from_share(fake_share) 

931 self.assertEqual(fake_host.total_capacity_gb, 'unknown') 

932 self.assertEqual(fake_host.free_capacity_gb, 'unknown') 

933 self.assertIsNone(fake_host.provisioned_capacity_gb) 

934 self.assertEqual(fake_host.allocated_capacity_gb, share_size) 

935 

936 def test_consume_from_share_invalid_capacity(self): 

937 fake_host = host_manager.PoolState('host1', {}, '_pool0') 

938 fake_host.free_capacity_gb = 'invalid_foo_string' 

939 fake_host.provisioned_capacity_gb = None 

940 fake_host.allocated_capacity_gb = 0 

941 fake_share = {'id': 'fake', 'size': 10} 

942 

943 self.assertRaises(exception.InvalidCapacity, 

944 fake_host.consume_from_share, fake_share) 

945 

946 def test_repr(self): 

947 

948 capability = { 

949 'share_backend_name': 'Backend1', 

950 'vendor_name': 'OpenStack', 

951 'driver_version': '1.0', 

952 'storage_protocol': 'NFS_CIFS', 

953 'total_capacity_gb': 20000, 

954 'free_capacity_gb': 15000, 

955 'allocated_capacity_gb': 5000, 

956 'timestamp': None, 

957 'reserved_percentage': 0, 

958 'reserved_snapshot_percentage': 0, 

959 'reserved_share_extend_percentage': 0, 

960 } 

961 fake_context = context.RequestContext('user', 'project', is_admin=True) 

962 fake_host = host_manager.HostState('host1') 

963 fake_host.update_from_share_capability(capability, 

964 context=fake_context) 

965 

966 result = fake_host.__repr__() 

967 expected = ("host: 'host1', free_capacity_gb: None, " 

968 "pools: {'Backend1': host: 'host1#Backend1', " 

969 "free_capacity_gb: 15000, pools: None}") 

970 self.assertEqual(expected, result) 

971 

972 

973@ddt.ddt 

974class PoolStateTestCase(test.TestCase): 

975 """Test case for HostState class.""" 

976 

977 @ddt.data( 

978 { 

979 'share_capability': 

980 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

981 'reserved_percentage': 0, 'timestamp': None, 

982 'reserved_snapshot_percentage': 0, 

983 'reserved_share_extend_percentage': 0, 

984 'thin_provisioning': True, 

985 'cap1': 'val1', 'cap2': 'val2'}, 

986 'instances': 

987 [ 

988 { 

989 'id': 1, 'host': 'host1', 

990 'status': 'available', 

991 'share_id': 11, 'size': 4, 

992 'updated_at': timeutils.utcnow() 

993 }, 

994 { 

995 'id': 2, 'host': 'host1', 

996 'status': 'available', 

997 'share_id': 12, 'size': None, 

998 'updated_at': timeutils.utcnow() 

999 }, 

1000 ] 

1001 }, 

1002 { 

1003 'share_capability': 

1004 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1005 'reserved_percentage': 0, 'timestamp': None, 

1006 'reserved_snapshot_percentage': 0, 

1007 'reserved_share_extend_percentage': 0, 

1008 'thin_provisioning': False, 'cap1': 'val1', 'cap2': 'val2'}, 

1009 'instances': 

1010 [ 

1011 { 

1012 'id': 1, 'host': 'host1', 

1013 'status': 'available', 

1014 'share_id': 11, 'size': 1, 

1015 'updated_at': timeutils.utcnow() 

1016 }, 

1017 { 

1018 'id': 2, 'host': 'host1', 

1019 'status': 'available', 

1020 'share_id': 12, 'size': None, 

1021 'updated_at': timeutils.utcnow() 

1022 }, 

1023 ] 

1024 }, 

1025 { 

1026 'share_capability': 

1027 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1028 'reserved_percentage': 0, 'timestamp': None, 

1029 'reserved_snapshot_percentage': 0, 

1030 'reserved_share_extend_percentage': 0, 

1031 'thin_provisioning': [False], 'cap1': 'val1', 'cap2': 'val2'}, 

1032 'instances': 

1033 [ 

1034 { 

1035 'id': 1, 'host': 'host1', 

1036 'status': 'available', 

1037 'share_id': 11, 'size': 1, 

1038 'updated_at': timeutils.utcnow() 

1039 }, 

1040 { 

1041 'id': 2, 'host': 'host1', 

1042 'status': 'available', 

1043 'share_id': 12, 'size': None, 

1044 'updated_at': timeutils.utcnow() 

1045 }, 

1046 ] 

1047 }, 

1048 { 

1049 'share_capability': 

1050 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1051 'reserved_percentage': 0, 'timestamp': None, 

1052 'reserved_snapshot_percentage': 0, 

1053 'reserved_share_extend_percentage': 0, 

1054 'thin_provisioning': [True, False], 'cap1': 'val1', 

1055 'cap2': 'val2'}, 

1056 'instances': 

1057 [ 

1058 { 

1059 'id': 1, 'host': 'host1', 

1060 'status': 'available', 

1061 'share_id': 11, 'size': 4, 

1062 'updated_at': timeutils.utcnow() 

1063 }, 

1064 { 

1065 'id': 2, 'host': 'host1', 

1066 'status': 'available', 

1067 'share_id': 12, 'size': None, 

1068 'updated_at': timeutils.utcnow() 

1069 }, 

1070 ] 

1071 }, 

1072 { 

1073 'share_capability': 

1074 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1075 'reserved_percentage': 0, 'timestamp': None, 

1076 'reserved_snapshot_percentage': 0, 

1077 'reserved_share_extend_percentage': 0, 

1078 'cap1': 'val1', 'cap2': 'val2', 'ipv4_support': True, 

1079 'ipv6_support': False}, 

1080 'instances': [] 

1081 }, 

1082 { 

1083 'share_capability': 

1084 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1085 'reserved_percentage': 0, 'timestamp': None, 

1086 'reserved_snapshot_percentage': 0, 

1087 'reserved_share_extend_percentage': 0, 

1088 'thin_provisioning': True, 'cap1': 'val1', 'cap2': 'val2', 

1089 'ipv4_support': True, 'ipv6_support': False}, 

1090 'instances': [] 

1091 }, 

1092 { 

1093 'share_capability': 

1094 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1095 'reserved_percentage': 0, 'timestamp': None, 

1096 'reserved_snapshot_percentage': 0, 

1097 'reserved_share_extend_percentage': 0, 

1098 'thin_provisioning': [False], 'cap1': 'val1', 'cap2': 'val2', 

1099 'ipv4_support': True, 'ipv6_support': False}, 

1100 'instances': [] 

1101 }, 

1102 { 

1103 'share_capability': 

1104 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1105 'reserved_percentage': 0, 'timestamp': None, 

1106 'reserved_snapshot_percentage': 0, 

1107 'reserved_share_extend_percentage': 0, 

1108 'thin_provisioning': [True, False], 'cap1': 'val1', 

1109 'cap2': 'val2', 'ipv4_support': True, 'ipv6_support': False}, 

1110 'instances': [] 

1111 }, 

1112 { 

1113 'share_capability': 

1114 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1115 'allocated_capacity_gb': 256, 'reserved_percentage': 0, 

1116 'reserved_snapshot_percentage': 0, 

1117 'reserved_share_extend_percentage': 0, 

1118 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2', 

1119 'ipv4_support': False, 'ipv6_support': True 

1120 }, 

1121 'instances': 

1122 [ 

1123 { 

1124 'id': 1, 'host': 'host1', 

1125 'status': 'available', 

1126 'share_id': 11, 'size': 4, 

1127 'updated_at': timeutils.utcnow() 

1128 }, 

1129 ] 

1130 }, 

1131 { 

1132 'share_capability': 

1133 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1134 'allocated_capacity_gb': 256, 'reserved_percentage': 0, 

1135 'reserved_snapshot_percentage': 0, 

1136 'reserved_share_extend_percentage': 0, 

1137 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2', 

1138 'ipv4_support': True, 'ipv6_support': True}, 

1139 'instances': [] 

1140 }, 

1141 { 

1142 'share_capability': 

1143 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1144 'provisioned_capacity_gb': 256, 'reserved_percentage': 0, 

1145 'reserved_snapshot_percentage': 0, 

1146 'reserved_share_extend_percentage': 0, 

1147 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2', 

1148 'ipv4_support': False, 'ipv6_support': False 

1149 }, 

1150 'instances': 

1151 [ 

1152 { 

1153 'id': 1, 'host': 'host1', 

1154 'status': 'available', 

1155 'share_id': 11, 'size': 1, 

1156 'updated_at': timeutils.utcnow() 

1157 }, 

1158 ] 

1159 }, 

1160 { 

1161 'share_capability': 

1162 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1163 'allocated_capacity_gb': 256, 'provisioned_capacity_gb': 1, 

1164 'thin_provisioning': True, 'reserved_percentage': 0, 

1165 'reserved_snapshot_percentage': 0, 

1166 'reserved_share_extend_percentage': 0, 

1167 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2'}, 

1168 'instances': 

1169 [ 

1170 { 

1171 'id': 1, 'host': 'host1', 

1172 'status': 'available', 

1173 'share_id': 11, 'size': 1, 

1174 'updated_at': timeutils.utcnow() 

1175 }, 

1176 ] 

1177 }, 

1178 { 

1179 'share_capability': 

1180 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1181 'allocated_capacity_gb': 256, 'provisioned_capacity_gb': 1, 

1182 'thin_provisioning': [False], 'reserved_percentage': 0, 

1183 'reserved_snapshot_percentage': 0, 

1184 'reserved_share_extend_percentage': 0, 

1185 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2'}, 

1186 'instances': 

1187 [ 

1188 { 

1189 'id': 1, 'host': 'host1', 

1190 'status': 'available', 

1191 'share_id': 11, 'size': 1, 

1192 'updated_at': timeutils.utcnow() 

1193 }, 

1194 ] 

1195 }, 

1196 { 

1197 'share_capability': 

1198 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1199 'allocated_capacity_gb': 256, 'provisioned_capacity_gb': 1, 

1200 'thin_provisioning': [True, False], 'reserved_percentage': 0, 

1201 'reserved_snapshot_percentage': 0, 

1202 'reserved_share_extend_percentage': 0, 

1203 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2'}, 

1204 'instances': 

1205 [ 

1206 { 

1207 'id': 1, 'host': 'host1', 

1208 'status': 'available', 

1209 'share_id': 11, 'size': 1, 

1210 'updated_at': timeutils.utcnow() 

1211 }, 

1212 ] 

1213 }, 

1214 { 

1215 'share_capability': 

1216 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1217 'allocated_capacity_gb': 256, 'provisioned_capacity_gb': 256, 

1218 'thin_provisioning': False, 'reserved_percentage': 0, 

1219 'reserved_snapshot_percentage': 0, 

1220 'reserved_share_extend_percentage': 0, 

1221 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2'}, 

1222 'instances': 

1223 [ 

1224 { 

1225 'id': 1, 'host': 'host1', 

1226 'status': 'available', 

1227 'share_id': 11, 'size': 1, 

1228 'updated_at': timeutils.utcnow() 

1229 }, 

1230 ] 

1231 }, 

1232 { 

1233 'share_capability': 

1234 {'total_capacity_gb': 1024, 'free_capacity_gb': 512, 

1235 'allocated_capacity_gb': 256, 'provisioned_capacity_gb': 256, 

1236 'thin_provisioning': [False], 'reserved_percentage': 0, 

1237 'reserved_snapshot_percentage': 0, 

1238 'reserved_share_extend_percentage': 0, 

1239 'timestamp': None, 'cap1': 'val1', 'cap2': 'val2'}, 

1240 'instances': 

1241 [ 

1242 { 

1243 'id': 1, 'host': 'host1', 

1244 'status': 'available', 

1245 'share_id': 11, 'size': 1, 

1246 'updated_at': timeutils.utcnow() 

1247 }, 

1248 ] 

1249 }, 

1250 ) 

1251 @ddt.unpack 

1252 def test_update_from_share_capability(self, share_capability, instances): 

1253 fake_context = context.RequestContext('user', 'project', is_admin=True) 

1254 sizes = [instance['size'] or 0 for instance in instances] 

1255 self.mock_object( 

1256 db, 'share_instance_sizes_sum_by_host', 

1257 mock.Mock(return_value=sum(sizes))) 

1258 fake_pool = host_manager.PoolState('host1', None, 'pool0') 

1259 self.assertIsNone(fake_pool.free_capacity_gb) 

1260 

1261 fake_pool.update_from_share_capability(share_capability, 

1262 context=fake_context) 

1263 

1264 self.assertEqual('host1#pool0', fake_pool.host) 

1265 self.assertEqual('pool0', fake_pool.pool_name) 

1266 self.assertEqual(1024, fake_pool.total_capacity_gb) 

1267 self.assertEqual(512, fake_pool.free_capacity_gb) 

1268 self.assertDictEqual(share_capability, dict(fake_pool.capabilities)) 

1269 

1270 if 'thin_provisioning' in share_capability: 

1271 thin_provisioned = scheduler_utils.thin_provisioning( 

1272 share_capability['thin_provisioning']) 

1273 else: 

1274 thin_provisioned = False 

1275 

1276 if thin_provisioned: 

1277 self.assertEqual(thin_provisioned, fake_pool.thin_provisioning) 

1278 if 'provisioned_capacity_gb' not in share_capability or ( 

1279 share_capability['provisioned_capacity_gb'] is None): 

1280 db.share_instance_sizes_sum_by_host.assert_called_once_with( 

1281 fake_context, fake_pool.host) 

1282 if len(instances) > 0: 

1283 self.assertEqual(4, fake_pool.provisioned_capacity_gb) 

1284 else: 

1285 self.assertEqual(0, fake_pool.provisioned_capacity_gb) 

1286 else: 

1287 self.assertFalse(db.share_instance_sizes_sum_by_host.called) 

1288 self.assertEqual(share_capability['provisioned_capacity_gb'], 

1289 fake_pool.provisioned_capacity_gb) 

1290 else: 

1291 self.assertFalse(fake_pool.thin_provisioning) 

1292 self.assertFalse(db.share_instance_sizes_sum_by_host.called) 

1293 if 'provisioned_capacity_gb' not in share_capability or ( 

1294 share_capability['provisioned_capacity_gb'] is None): 

1295 self.assertIsNone(fake_pool.provisioned_capacity_gb) 

1296 else: 

1297 self.assertEqual(share_capability['provisioned_capacity_gb'], 

1298 fake_pool.provisioned_capacity_gb) 

1299 

1300 if 'allocated_capacity_gb' in share_capability: 

1301 self.assertEqual(share_capability['allocated_capacity_gb'], 

1302 fake_pool.allocated_capacity_gb) 

1303 else: 

1304 self.assertEqual(0, fake_pool.allocated_capacity_gb) 

1305 

1306 if 'ipv4_support' in share_capability: 

1307 self.assertEqual(share_capability['ipv4_support'], 

1308 fake_pool.ipv4_support) 

1309 if 'ipv6_support' in share_capability: 

1310 self.assertEqual(share_capability['ipv6_support'], 

1311 fake_pool.ipv6_support)