Coverage for manila/tests/scheduler/filters/test_capacity.py: 99%

101 statements  

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

1# Copyright 2011 OpenStack LLC. # All Rights Reserved. 

2# 

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

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

5# a copy of the License at 

6# 

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

8# 

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

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

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

12# License for the specific language governing permissions and limitations 

13# under the License. 

14""" 

15Tests For CapacityFilter. 

16""" 

17 

18import ddt 

19 

20from manila.scheduler.filters import capacity 

21from manila import test 

22from manila.tests.scheduler import fakes 

23from manila import utils 

24 

25 

26@ddt.ddt 

27class HostFiltersTestCase(test.TestCase): 

28 """Test case CapacityFilter.""" 

29 

30 def setUp(self): 

31 super(HostFiltersTestCase, self).setUp() 

32 self.filter = capacity.CapacityFilter() 

33 

34 def _stub_service_is_up(self, ret_value): 

35 def fake_service_is_up(service): 

36 return ret_value 

37 self.mock_object(utils, 'service_is_up', fake_service_is_up) 

38 

39 @ddt.data( 

40 {'size': 100, 'share_on': None, 'host': 'host1'}, 

41 {'size': 100, 'share_on': 'host1#pool1', 'host': 'host1#pools1'}) 

42 @ddt.unpack 

43 def test_capacity_filter_passes(self, size, share_on, host): 

44 self._stub_service_is_up(True) 

45 filter_properties = {'size': size, 

46 'share_exists_on': share_on} 

47 service = {'disabled': False} 

48 host = fakes.FakeHostState(host, 

49 {'total_capacity_gb': 500, 

50 'free_capacity_gb': 200, 

51 'updated_at': None, 

52 'service': service}) 

53 self.assertTrue(self.filter.host_passes(host, filter_properties)) 

54 

55 @ddt.data( 

56 {'free_capacity': 120, 'total_capacity': 200, 

57 'reserved': 20}, 

58 {'free_capacity': None, 'total_capacity': None, 

59 'reserved': None}) 

60 @ddt.unpack 

61 def test_capacity_filter_fails(self, free_capacity, total_capacity, 

62 reserved): 

63 self._stub_service_is_up(True) 

64 filter_properties = {'size': 100} 

65 service = {'disabled': False} 

66 host = fakes.FakeHostState('host1', 

67 {'total_capacity_gb': total_capacity, 

68 'free_capacity_gb': free_capacity, 

69 'reserved_percentage': reserved, 

70 'updated_at': None, 

71 'service': service}) 

72 self.assertFalse(self.filter.host_passes(host, filter_properties)) 

73 

74 @ddt.data( 

75 {'free_capacity': 120, 'total_capacity': 200, 

76 'reserved': 20, 'reserved_snapshot': 5}) 

77 @ddt.unpack 

78 def test_capacity_filter_passes_snapshot_reserved(self, free_capacity, 

79 total_capacity, 

80 reserved, 

81 reserved_snapshot): 

82 self._stub_service_is_up(True) 

83 filter_properties = {'size': 100, 'snapshot_id': 1234} 

84 service = {'disabled': False} 

85 host = fakes.FakeHostState('host1', 

86 {'total_capacity_gb': total_capacity, 

87 'free_capacity_gb': free_capacity, 

88 'reserved_percentage': reserved, 

89 'reserved_snapshot_percentage': 

90 reserved_snapshot, 

91 'updated_at': None, 

92 'service': service}) 

93 self.assertTrue(self.filter.host_passes(host, filter_properties)) 

94 

95 @ddt.data( 

96 {'free_capacity': 120, 'total_capacity': 200, 

97 'reserved': 20, 'reserved_snapshot': 15}) 

98 @ddt.unpack 

99 def test_capacity_filter_fails_snapshot_reserved(self, free_capacity, 

100 total_capacity, 

101 reserved, 

102 reserved_snapshot): 

103 self._stub_service_is_up(True) 

104 filter_properties = {'size': 100, 'snapshot_id': 1234} 

105 service = {'disabled': False} 

106 host = fakes.FakeHostState('host1', 

107 {'total_capacity_gb': total_capacity, 

108 'free_capacity_gb': free_capacity, 

109 'reserved_percentage': reserved, 

110 'reserved_snapshot_percentage': 

111 reserved_snapshot, 

112 'updated_at': None, 

113 'service': service}) 

114 self.assertFalse(self.filter.host_passes(host, filter_properties)) 

115 

116 @ddt.data( 

117 {'free_capacity': 120, 'total_capacity': 200, 

118 'reserved': 20, 'reserved_share_extend_percentage': 5}) 

119 @ddt.unpack 

120 def test_capacity_filter_passes_share_extend_reserved( 

121 self, free_capacity, 

122 total_capacity, 

123 reserved, 

124 reserved_share_extend_percentage): 

125 self._stub_service_is_up(True) 

126 filter_properties = {'size': 100, 'is_share_extend': True} 

127 service = {'disabled': False} 

128 host = fakes.FakeHostState('host1', 

129 {'total_capacity_gb': total_capacity, 

130 'free_capacity_gb': free_capacity, 

131 'reserved_percentage': reserved, 

132 'reserved_share_extend_percentage': 

133 reserved_share_extend_percentage, 

134 'updated_at': None, 

135 'service': service}) 

136 self.assertTrue(self.filter.host_passes(host, filter_properties)) 

137 

138 @ddt.data( 

139 {'free_capacity': 120, 'total_capacity': 200, 

140 'reserved': 20, 'reserved_share_extend_percentage': 15}) 

141 @ddt.unpack 

142 def test_capacity_filter_fails_share_extend_reserved( 

143 self, free_capacity, 

144 total_capacity, 

145 reserved, 

146 reserved_share_extend_percentage): 

147 self._stub_service_is_up(True) 

148 filter_properties = {'size': 100, 'is_share_extend': True} 

149 service = {'disabled': False} 

150 host = fakes.FakeHostState('host1', 

151 {'total_capacity_gb': total_capacity, 

152 'free_capacity_gb': free_capacity, 

153 'reserved_percentage': reserved, 

154 'reserved_share_extend_percentage': 

155 reserved_share_extend_percentage, 

156 'updated_at': None, 

157 'service': service}) 

158 self.assertFalse(self.filter.host_passes(host, filter_properties)) 

159 

160 def test_capacity_filter_passes_unknown(self): 

161 free = 'unknown' 

162 self._stub_service_is_up(True) 

163 filter_properties = {'size': 100} 

164 service = {'disabled': False} 

165 host = fakes.FakeHostState('host1', 

166 {'free_capacity_gb': free, 

167 'updated_at': None, 

168 'service': service}) 

169 self.assertTrue(self.filter.host_passes(host, filter_properties)) 

170 

171 @ddt.data( 

172 {'free_capacity': 'unknown', 'total_capacity': 'unknown'}, 

173 {'free_capacity': 200, 'total_capacity': 'unknown'}) 

174 @ddt.unpack 

175 def test_capacity_filter_passes_total(self, free_capacity, 

176 total_capacity): 

177 self._stub_service_is_up(True) 

178 filter_properties = {'size': 100} 

179 service = {'disabled': False} 

180 host = fakes.FakeHostState('host1', 

181 {'free_capacity_gb': free_capacity, 

182 'total_capacity_gb': total_capacity, 

183 'reserved_percentage': 0, 

184 'updated_at': None, 

185 'service': service}) 

186 self.assertTrue(self.filter.host_passes(host, filter_properties)) 

187 

188 @ddt.data( 

189 {'free': 200, 'total': 'unknown', 'reserved': 5}, 

190 {'free': 50, 'total': 'unknown', 'reserved': 0}, 

191 {'free': 200, 'total': 0, 'reserved': 0}) 

192 @ddt.unpack 

193 def test_capacity_filter_fails_total(self, free, total, reserved): 

194 self._stub_service_is_up(True) 

195 filter_properties = {'size': 100} 

196 service = {'disabled': False} 

197 host = fakes.FakeHostState('host1', 

198 {'free_capacity_gb': free, 

199 'total_capacity_gb': total, 

200 'reserved_percentage': reserved, 

201 'updated_at': None, 

202 'service': service}) 

203 self.assertFalse(self.filter.host_passes(host, filter_properties)) 

204 

205 @ddt.data( 

206 {'size': 100, 'cap_thin': '<is> True', 

207 'total': 500, 'free': 200, 'provisioned': 500, 

208 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

209 'cap_thin_key': 'capabilities:thin_provisioning'}, 

210 {'size': 3000, 'cap_thin': '<is> True', 

211 'total': 500, 'free': 200, 'provisioned': 7000, 

212 'max_ratio': 20, 'reserved': 5, 'thin_prov': True, 

213 'cap_thin_key': 'thin_provisioning'}, 

214 {'size': 100, 'cap_thin': '<is> False', 

215 'total': 500, 'free': 200, 'provisioned': 300, 

216 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False, 

217 'cap_thin_key': 'capabilities:thin_provisioning'}, 

218 {'size': 100, 'cap_thin': '<is> True', 

219 'total': 500, 'free': 200, 'provisioned': 400, 

220 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': True, 

221 'cap_thin_key': 'thin_provisioning'}, 

222 {'size': 100, 'cap_thin': '<is> True', 

223 'total': 500, 'free': 125, 'provisioned': 400, 

224 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

225 'cap_thin_key': 'capabilities:thin_provisioning'}, 

226 {'size': 100, 'cap_thin': '<is> True', 

227 'total': 500, 'free': 80, 'provisioned': 600, 

228 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

229 'cap_thin_key': 'thin_provisioning'}, 

230 {'size': 100, 'cap_thin': '<is> True', 

231 'total': 500, 'free': 100, 'provisioned': 400, 

232 'max_ratio': 2.0, 'reserved': 0, 'thin_prov': True, 

233 'cap_thin_key': 'capabilities:thin_provisioning'}, 

234 {'size': 100, 'cap_thin': '<is> True', 

235 'total': 500, 'free': 200, 'provisioned': 500, 

236 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [True, False], 

237 'cap_thin_key': 'thin_provisioning'}, 

238 {'size': 3000, 'cap_thin': '<is> True', 

239 'total': 500, 'free': 200, 'provisioned': 7000, 

240 'max_ratio': 20, 'reserved': 5, 'thin_prov': [True], 

241 'cap_thin_key': 'capabilities:thin_provisioning'}, 

242 {'size': 100, 'cap_thin': '<is> False', 

243 'total': 500, 'free': 200, 'provisioned': 300, 

244 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False], 

245 'cap_thin_key': 'thin_provisioning'}, 

246 {'size': 100, 'cap_thin': 'True', 

247 'total': 500, 'free': 200, 'provisioned': 400, 

248 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False, True], 

249 'cap_thin_key': 'capabilities:thin_provisioning'}, 

250 {'size': 100, 'cap_thin': 'False', 

251 'total': 500, 'free': 200, 'provisioned': 300, 

252 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False, 

253 'cap_thin_key': 'thin_provisioning'}, 

254 {'size': 100, 'cap_thin': 'true', 

255 'total': 500, 'free': 125, 'provisioned': 400, 

256 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [True, ], 

257 'cap_thin_key': 'capabilities:thin_provisioning'}, 

258 {'size': 100, 'cap_thin': 'false', 

259 'total': 500, 'free': 200, 'provisioned': 300, 

260 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False, ], 

261 'cap_thin_key': 'thin_provisioning'}, 

262 {'size': 100, 'cap_thin': None, 

263 'total': 500, 'free': 80, 'provisioned': 600, 

264 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

265 'cap_thin_key': None},) 

266 @ddt.unpack 

267 def test_filter_thin_passes(self, size, cap_thin, total, free, provisioned, 

268 max_ratio, reserved, thin_prov, cap_thin_key): 

269 self._stub_service_is_up(True) 

270 filter_properties = { 

271 'size': size, 

272 'snapshot_id': None, 

273 'share_type': { 

274 'extra_specs': { 

275 cap_thin_key: cap_thin, 

276 } 

277 } 

278 } 

279 service = {'disabled': False} 

280 host = fakes.FakeHostState('host1', 

281 {'total_capacity_gb': total, 

282 'free_capacity_gb': free, 

283 'provisioned_capacity_gb': provisioned, 

284 'max_over_subscription_ratio': max_ratio, 

285 'reserved_percentage': reserved, 

286 'thin_provisioning': thin_prov, 

287 'updated_at': None, 

288 'service': service}) 

289 self.assertTrue(self.filter.host_passes(host, filter_properties)) 

290 

291 @ddt.data( 

292 {'size': 200, 'cap_thin': '<is> True', 

293 'total': 500, 'free': 100, 'provisioned': 400, 

294 'max_ratio': 0.8, 'reserved': 0, 'thin_prov': True, 

295 'cap_thin_key': 'capabilities:thin_provisioning'}, 

296 {'size': 100, 'cap_thin': '<is> True', 

297 'total': 500, 'free': 200, 'provisioned': 700, 

298 'max_ratio': 1.5, 'reserved': 5, 'thin_prov': True, 

299 'cap_thin_key': 'thin_provisioning'}, 

300 {'size': 2000, 'cap_thin': '<is> True', 

301 'total': 500, 'free': 30, 'provisioned': 9000, 

302 'max_ratio': 20.0, 'reserved': 0, 'thin_prov': True, 

303 'cap_thin_key': 'capabilities:thin_provisioning'}, 

304 {'size': 100, 'cap_thin': '<is> True', 

305 'total': 500, 'free': 100, 'provisioned': 1000, 

306 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

307 'cap_thin_key': 'thin_provisioning'}, 

308 {'size': 100, 'cap_thin': '<is> False', 

309 'total': 500, 'free': 100, 'provisioned': 400, 

310 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False, 

311 'cap_thin_key': 'capabilities:thin_provisioning'}, 

312 {'size': 100, 'cap_thin': '<is> True', 

313 'total': 500, 'free': 0, 'provisioned': 800, 

314 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

315 'cap_thin_key': 'thin_provisioning'}, 

316 {'size': 100, 'cap_thin': '<is> True', 

317 'total': 500, 'free': 99, 'provisioned': 1000, 

318 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

319 'cap_thin_key': 'capabilities:thin_provisioning'}, 

320 {'size': 400, 'cap_thin': '<is> True', 

321 'total': 500, 'free': 200, 'provisioned': 600, 

322 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True, 

323 'cap_thin_key': 'thin_provisioning'}, 

324 {'size': 200, 'cap_thin': '<is> True', 

325 'total': 500, 'free': 100, 'provisioned': 400, 

326 'max_ratio': 0.8, 'reserved': 0, 'thin_prov': [False, True], 

327 'cap_thin_key': 'capabilities:thin_provisioning'}, 

328 {'size': 2000, 'cap_thin': '<is> True', 

329 'total': 500, 'free': 30, 'provisioned': 9000, 

330 'max_ratio': 20.0, 'reserved': 0, 'thin_prov': [True], 

331 'cap_thin_key': 'thin_provisioning'}, 

332 {'size': 100, 'cap_thin': '<is> False', 

333 'total': 500, 'free': 100, 'provisioned': 400, 

334 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False], 

335 'cap_thin_key': 'thin_provisioning'}, 

336 {'size': 100, 'cap_thin': 'False', 

337 'total': 500, 'free': 100, 'provisioned': 400, 

338 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False, 

339 'cap_thin_key': 'capabilities:thin_provisioning'}, 

340 {'size': 100, 'cap_thin': 'True', 

341 'total': 500, 'free': 0, 'provisioned': 800, 

342 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [False, True], 

343 'cap_thin_key': 'thin_provisioning'}, 

344 {'size': 100, 'cap_thin': 'true', 

345 'total': 500, 'free': 99, 'provisioned': 1000, 

346 'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [True, ], 

347 'cap_thin_key': 'capabilities:thin_provisioning'}, 

348 {'size': 100, 'cap_thin': 'false', 

349 'total': 500, 'free': 100, 'provisioned': 400, 

350 'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False, ], 

351 'cap_thin_key': 'thin_provisioning'}, 

352 {'size': 2000, 'cap_thin': None, 

353 'total': 500, 'free': 30, 'provisioned': 9000, 

354 'max_ratio': 20.0, 'reserved': 0, 'thin_prov': [True], 

355 'cap_thin_key': None},) 

356 @ddt.unpack 

357 def test_filter_thin_fails(self, size, cap_thin, total, free, provisioned, 

358 max_ratio, reserved, thin_prov, cap_thin_key): 

359 self._stub_service_is_up(True) 

360 filter_properties = { 

361 'size': size, 

362 'share_type': { 

363 'extra_specs': { 

364 cap_thin_key: cap_thin, 

365 } 

366 } 

367 } 

368 service = {'disabled': False} 

369 host = fakes.FakeHostState('host1', 

370 {'total_capacity_gb': total, 

371 'free_capacity_gb': free, 

372 'provisioned_capacity_gb': provisioned, 

373 'max_over_subscription_ratio': max_ratio, 

374 'reserved_percentage': reserved, 

375 'thin_provisioning': thin_prov, 

376 'updated_at': None, 

377 'service': service}) 

378 self.assertFalse(self.filter.host_passes(host, filter_properties))