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
« 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"""
18import ddt
20from manila.scheduler.filters import capacity
21from manila import test
22from manila.tests.scheduler import fakes
23from manila import utils
26@ddt.ddt
27class HostFiltersTestCase(test.TestCase):
28 """Test case CapacityFilter."""
30 def setUp(self):
31 super(HostFiltersTestCase, self).setUp()
32 self.filter = capacity.CapacityFilter()
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)
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))
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))
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))
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))
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))
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))
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))
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))
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))
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))
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))