]>
git.proxmox.com Git - ceph.git/blob - ceph/src/ceph-volume/ceph_volume/tests/util/test_disk.py
3 from ceph_volume
.util
import disk
6 class TestLsblkParser(object):
8 def test_parses_whitespace_values(self
):
9 output
= 'NAME="sdaa5" PARTLABEL="ceph data" RM="0" SIZE="10M" RO="0" TYPE="part"'
10 result
= disk
._lsblk
_parser
(output
)
11 assert result
['PARTLABEL'] == 'ceph data'
13 def test_ignores_bogus_pairs(self
):
14 output
= 'NAME="sdaa5" PARTLABEL RM="0" SIZE="10M" RO="0" TYPE="part" MOUNTPOINT=""'
15 result
= disk
._lsblk
_parser
(output
)
16 assert result
['SIZE'] == '10M'
19 class TestDeviceFamily(object):
21 def test_groups_multiple_devices(self
, stub_call
):
23 'NAME="sdaa5" PARLABEL="ceph lockbox"',
25 'NAME="sdaa1" PARLABEL="ceph data"',
26 'NAME="sdaa2" PARLABEL="ceph journal"',
28 stub_call((out
, '', 0))
29 result
= disk
.device_family('sdaa5')
30 assert len(result
) == 4
32 def test_parses_output_correctly(self
, stub_call
):
33 names
= ['sdaa', 'sdaa5', 'sdaa1', 'sdaa2']
35 'NAME="sdaa5" PARLABEL="ceph lockbox"',
37 'NAME="sdaa1" PARLABEL="ceph data"',
38 'NAME="sdaa2" PARLABEL="ceph journal"',
40 stub_call((out
, '', 0))
41 result
= disk
.device_family('sdaa5')
43 assert parsed
['NAME'] in names
46 class TestMapDevPaths(object):
48 def test_errors_return_empty_mapping(self
, tmpdir
):
49 bad_dir
= os
.path
.join(str(tmpdir
), 'nonexisting')
50 assert disk
._map
_dev
_paths
(bad_dir
) == {}
52 def test_base_name_and_abspath(self
, tmpfile
):
53 sda_path
= tmpfile(name
='sda', contents
='')
54 directory
= os
.path
.dirname(sda_path
)
55 result
= disk
._map
_dev
_paths
(directory
)
56 assert len(result
.keys()) == 1
57 assert result
['sda'] == sda_path
59 def test_abspath_included(self
, tmpfile
):
60 sda_path
= tmpfile(name
='sda', contents
='')
61 directory
= os
.path
.dirname(sda_path
)
62 result
= disk
._map
_dev
_paths
(directory
, include_abspath
=True)
63 assert sorted(result
.keys()) == sorted(['sda', sda_path
])
64 assert result
['sda'] == sda_path
65 assert result
[sda_path
] == 'sda'
67 def test_realpath_included(self
, tmpfile
):
68 sda_path
= tmpfile(name
='sda', contents
='')
69 directory
= os
.path
.dirname(sda_path
)
70 dm_path
= os
.path
.join(directory
, 'dm-0')
71 os
.symlink(sda_path
, os
.path
.join(directory
, 'dm-0'))
72 result
= disk
._map
_dev
_paths
(directory
, include_realpath
=True)
73 assert sorted(result
.keys()) == sorted(['sda', 'dm-0'])
74 assert result
['sda'] == dm_path
75 assert result
['dm-0'] == dm_path
77 def test_absolute_and_realpath_included(self
, tmpfile
):
78 dm_path
= tmpfile(name
='dm-0', contents
='')
79 directory
= os
.path
.dirname(dm_path
)
80 sda_path
= os
.path
.join(directory
, 'sda')
81 os
.symlink(sda_path
, os
.path
.join(directory
, 'sda'))
82 result
= disk
._map
_dev
_paths
(directory
, include_realpath
=True, include_abspath
=True)
83 assert sorted(result
.keys()) == sorted([dm_path
, sda_path
, 'sda', 'dm-0'])
84 assert result
['sda'] == sda_path
85 assert result
['dm-0'] == dm_path
86 assert result
[sda_path
] == sda_path
87 assert result
[dm_path
] == 'dm-0'
90 class TestGetBlockDevs(object):
92 def test_loop_devices_are_missing(self
, tmpfile
):
93 path
= os
.path
.dirname(tmpfile(name
='loop0', contents
=''))
94 result
= disk
.get_block_devs(sys_block_path
=path
)
97 def test_loop_devices_are_included(self
, tmpfile
):
98 path
= os
.path
.dirname(tmpfile(name
='loop0', contents
=''))
99 result
= disk
.get_block_devs(sys_block_path
=path
, skip_loop
=False)
100 assert len(result
) == 1
101 assert result
== ['loop0']
104 class TestGetDevDevs(object):
106 def test_abspaths_are_included(self
, tmpfile
):
107 sda_path
= tmpfile(name
='sda', contents
='')
108 directory
= os
.path
.dirname(sda_path
)
109 result
= disk
.get_dev_devs(directory
)
110 assert sorted(result
.keys()) == sorted(['sda', sda_path
])
111 assert result
['sda'] == sda_path
112 assert result
[sda_path
] == 'sda'
115 class TestGetMapperDevs(object):
117 def test_abspaths_and_realpaths_are_included(self
, tmpfile
):
118 dm_path
= tmpfile(name
='dm-0', contents
='')
119 directory
= os
.path
.dirname(dm_path
)
120 sda_path
= os
.path
.join(directory
, 'sda')
121 os
.symlink(sda_path
, os
.path
.join(directory
, 'sda'))
122 result
= disk
.get_mapper_devs(directory
)
123 assert sorted(result
.keys()) == sorted([dm_path
, sda_path
, 'sda', 'dm-0'])
124 assert result
['sda'] == sda_path
125 assert result
['dm-0'] == dm_path
126 assert result
[sda_path
] == sda_path
127 assert result
[dm_path
] == 'dm-0'
130 class TestHumanReadableSize(object):
132 def test_bytes(self
):
133 result
= disk
.human_readable_size(800)
134 assert result
== '800.00 B'
136 def test_kilobytes(self
):
137 result
= disk
.human_readable_size(800*1024)
138 assert result
== '800.00 KB'
140 def test_megabytes(self
):
141 result
= disk
.human_readable_size(800*1024*1024)
142 assert result
== '800.00 MB'
144 def test_gigabytes(self
):
145 result
= disk
.human_readable_size(8.19*1024*1024*1024)
146 assert result
== '8.19 GB'
148 def test_terabytes(self
):
149 result
= disk
.human_readable_size(81.2*1024*1024*1024*1024)
150 assert result
== '81.20 TB'
153 class TestGetDevices(object):
155 def setup_paths(self
, tmpdir
):
157 for directory
in ['block', 'dev', 'mapper']:
158 path
= os
.path
.join(str(tmpdir
), directory
)
163 def test_no_devices_are_found(self
, tmpdir
):
164 result
= disk
.get_devices(
165 _sys_block_path
=str(tmpdir
),
166 _dev_path
=str(tmpdir
),
167 _mapper_path
=str(tmpdir
))
170 def test_sda_block_is_found(self
, tmpfile
, tmpdir
):
171 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
172 dev_sda_path
= os
.path
.join(dev_path
, 'sda')
173 os
.makedirs(os
.path
.join(block_path
, 'sda'))
174 os
.makedirs(dev_sda_path
)
175 result
= disk
.get_devices(
176 _sys_block_path
=block_path
,
178 _mapper_path
=mapper_path
)
179 assert len(result
.keys()) == 1
180 assert result
[dev_sda_path
]['human_readable_size'] == '0.00 B'
181 assert result
[dev_sda_path
]['model'] == ''
182 assert result
[dev_sda_path
]['partitions'] == {}
184 def test_sda_is_removable_gets_skipped(self
, tmpfile
, tmpdir
):
185 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
186 dev_sda_path
= os
.path
.join(dev_path
, 'sda')
187 block_sda_path
= os
.path
.join(block_path
, 'sda')
188 os
.makedirs(block_sda_path
)
189 os
.makedirs(dev_sda_path
)
191 tmpfile('removable', contents
='1', directory
=block_sda_path
)
192 result
= disk
.get_devices(
193 _sys_block_path
=block_path
,
195 _mapper_path
=mapper_path
)
198 def test_dm_device_is_not_used(self
, monkeypatch
, tmpdir
):
199 # the link to the mapper is used instead
200 monkeypatch
.setattr(disk
.lvm
, 'is_lv', lambda: True)
201 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
202 dev_dm_path
= os
.path
.join(dev_path
, 'dm-0')
203 ceph_data_path
= os
.path
.join(mapper_path
, 'ceph-data')
204 os
.symlink(dev_dm_path
, ceph_data_path
)
205 block_dm_path
= os
.path
.join(block_path
, 'dm-0')
206 os
.makedirs(block_dm_path
)
208 result
= disk
.get_devices(
209 _sys_block_path
=block_path
,
211 _mapper_path
=mapper_path
)
212 result
= list(result
.keys())
213 assert len(result
) == 1
214 assert result
== [ceph_data_path
]
216 def test_sda_size(self
, tmpfile
, tmpdir
):
217 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
218 block_sda_path
= os
.path
.join(block_path
, 'sda')
219 dev_sda_path
= os
.path
.join(dev_path
, 'sda')
220 os
.makedirs(block_sda_path
)
221 os
.makedirs(dev_sda_path
)
222 tmpfile('size', '1024', directory
=block_sda_path
)
223 result
= disk
.get_devices(
224 _sys_block_path
=block_path
,
226 _mapper_path
=mapper_path
)
227 assert list(result
.keys()) == [dev_sda_path
]
228 assert result
[dev_sda_path
]['human_readable_size'] == '512.00 KB'
230 def test_sda_sectorsize_fallsback(self
, tmpfile
, tmpdir
):
231 # if no sectorsize, it will use queue/hw_sector_size
232 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
233 block_sda_path
= os
.path
.join(block_path
, 'sda')
234 sda_queue_path
= os
.path
.join(block_sda_path
, 'queue')
235 dev_sda_path
= os
.path
.join(dev_path
, 'sda')
236 os
.makedirs(block_sda_path
)
237 os
.makedirs(sda_queue_path
)
238 os
.makedirs(dev_sda_path
)
239 tmpfile('hw_sector_size', contents
='1024', directory
=sda_queue_path
)
240 result
= disk
.get_devices(
241 _sys_block_path
=block_path
,
243 _mapper_path
=mapper_path
)
244 assert list(result
.keys()) == [dev_sda_path
]
245 assert result
[dev_sda_path
]['sectorsize'] == '1024'
247 def test_sda_sectorsize_from_logical_block(self
, tmpfile
, tmpdir
):
248 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
249 block_sda_path
= os
.path
.join(block_path
, 'sda')
250 sda_queue_path
= os
.path
.join(block_sda_path
, 'queue')
251 dev_sda_path
= os
.path
.join(dev_path
, 'sda')
252 os
.makedirs(block_sda_path
)
253 os
.makedirs(sda_queue_path
)
254 os
.makedirs(dev_sda_path
)
255 tmpfile('logical_block_size', contents
='99', directory
=sda_queue_path
)
256 result
= disk
.get_devices(
257 _sys_block_path
=block_path
,
259 _mapper_path
=mapper_path
)
260 assert result
[dev_sda_path
]['sectorsize'] == '99'
262 def test_sda_sectorsize_does_not_fallback(self
, tmpfile
, tmpdir
):
263 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
264 block_sda_path
= os
.path
.join(block_path
, 'sda')
265 sda_queue_path
= os
.path
.join(block_sda_path
, 'queue')
266 dev_sda_path
= os
.path
.join(dev_path
, 'sda')
267 os
.makedirs(block_sda_path
)
268 os
.makedirs(sda_queue_path
)
269 os
.makedirs(dev_sda_path
)
270 tmpfile('logical_block_size', contents
='99', directory
=sda_queue_path
)
271 tmpfile('hw_sector_size', contents
='1024', directory
=sda_queue_path
)
272 result
= disk
.get_devices(
273 _sys_block_path
=block_path
,
275 _mapper_path
=mapper_path
)
276 assert result
[dev_sda_path
]['sectorsize'] == '99'
278 def test_is_rotational(self
, tmpfile
, tmpdir
):
279 block_path
, dev_path
, mapper_path
= self
.setup_paths(tmpdir
)
280 block_sda_path
= os
.path
.join(block_path
, 'sda')
281 sda_queue_path
= os
.path
.join(block_sda_path
, 'queue')
282 dev_sda_path
= os
.path
.join(dev_path
, 'sda')
283 os
.makedirs(block_sda_path
)
284 os
.makedirs(sda_queue_path
)
285 os
.makedirs(dev_sda_path
)
286 tmpfile('rotational', contents
='1', directory
=sda_queue_path
)
287 result
= disk
.get_devices(
288 _sys_block_path
=block_path
,
290 _mapper_path
=mapper_path
)
291 assert result
[dev_sda_path
]['rotational'] == '1'
294 class TestSizeCalculations(object):
296 @pytest.mark
.parametrize('aliases', [
303 def test_aliases(self
, aliases
):
304 short_alias
, long_alias
= aliases
306 short_alias
= getattr(s
, short_alias
)
307 long_alias
= getattr(s
, long_alias
)
308 assert short_alias
== long_alias
310 @pytest.mark
.parametrize('values', [
311 ('b', 857619069665.28),
312 ('kb', 837518622.72),
317 def test_terabytes(self
, values
):
318 # regardless of the input value, all the other values correlate to each
319 # other the same, every time
321 s
= disk
.Size(**{unit
: value
})
322 assert s
.b
== 857619069665.28
323 assert s
.kb
== 837518622.72
324 assert s
.mb
== 817889.28
325 assert s
.gb
== 798.72
329 class TestSizeOperators(object):
331 @pytest.mark
.parametrize('larger', [1025, 1024.1, 1024.001])
332 def test_gigabytes_is_smaller(self
, larger
):
333 assert disk
.Size(gb
=1) < disk
.Size(mb
=larger
)
335 @pytest.mark
.parametrize('smaller', [1023, 1023.9, 1023.001])
336 def test_gigabytes_is_larger(self
, smaller
):
337 assert disk
.Size(gb
=1) > disk
.Size(mb
=smaller
)
339 @pytest.mark
.parametrize('larger', [1025, 1024.1, 1024.001, 1024])
340 def test_gigabytes_is_smaller_or_equal(self
, larger
):
341 assert disk
.Size(gb
=1) <= disk
.Size(mb
=larger
)
343 @pytest.mark
.parametrize('smaller', [1023, 1023.9, 1023.001, 1024])
344 def test_gigabytes_is_larger_or_equal(self
, smaller
):
345 assert disk
.Size(gb
=1) >= disk
.Size(mb
=smaller
)
347 @pytest.mark
.parametrize('values', [
348 ('b', 857619069665.28),
349 ('kb', 837518622.72),
354 def test_equality(self
, values
):
356 s
= disk
.Size(**{unit
: value
})
357 # both tb and b, since b is always calculated regardless, and is useful
359 assert disk
.Size(tb
=0.78) == s
360 assert disk
.Size(b
=857619069665.28) == s
362 @pytest.mark
.parametrize('values', [
363 ('b', 857619069665.28),
364 ('kb', 837518622.72),
369 def test_inequality(self
, values
):
371 s
= disk
.Size(**{unit
: value
})
372 # both tb and b, since b is always calculated regardless, and is useful
374 assert disk
.Size(tb
=1) != s
375 assert disk
.Size(b
=100) != s
378 class TestSizeOperations(object):
380 def test_assignment_addition_with_size_objects(self
):
381 result
= disk
.Size(mb
=256) + disk
.Size(gb
=1)
382 assert result
.gb
== 1.25
383 assert result
.gb
.as_int() == 1
384 assert result
.gb
.as_float() == 1.25
386 def test_self_addition_with_size_objects(self
):
387 base
= disk
.Size(mb
=256)
388 base
+= disk
.Size(gb
=1)
389 assert base
.gb
== 1.25
391 def test_self_addition_does_not_alter_state(self
):
392 base
= disk
.Size(mb
=256)
393 base
+ disk
.Size(gb
=1)
394 assert base
.mb
== 256
396 def test_addition_with_non_size_objects(self
):
397 with pytest
.raises(TypeError):
398 disk
.Size(mb
=100) + 4
400 def test_assignment_subtraction_with_size_objects(self
):
401 base
= disk
.Size(gb
=1)
402 base
-= disk
.Size(mb
=256)
403 assert base
.mb
== 768
405 def test_self_subtraction_does_not_alter_state(self
):
406 base
= disk
.Size(gb
=1)
407 base
- disk
.Size(mb
=256)
410 def test_subtraction_with_size_objects(self
):
411 result
= disk
.Size(gb
=1) - disk
.Size(mb
=256)
412 assert result
.mb
== 768
414 def test_subtraction_with_non_size_objects(self
):
415 with pytest
.raises(TypeError):
416 disk
.Size(mb
=100) - 4
418 def test_multiplication_with_size_objects(self
):
419 with pytest
.raises(TypeError):
420 disk
.Size(mb
=100) * disk
.Size(mb
=1)
422 def test_multiplication_with_non_size_objects(self
):
423 base
= disk
.Size(gb
=1)
425 assert result
.gb
== 2
426 assert result
.gb
.as_int() == 2
428 def test_division_with_size_objects(self
):
429 result
= disk
.Size(gb
=1) / disk
.Size(mb
=1)
430 assert int(result
) == 1024
432 def test_division_with_non_size_objects(self
):
433 base
= disk
.Size(gb
=1)
435 assert base
.mb
== 512
436 assert base
.mb
.as_int() == 512
439 class TestSizeAttributes(object):
441 def test_attribute_does_not_exist(self
):
442 with pytest
.raises(AttributeError):
443 disk
.Size(mb
=1).exabytes
446 class TestSizeFormatting(object):
448 def test_default_formatting_tb_to_b(self
):
449 size
= disk
.Size(tb
=0.0000000001)
451 assert result
== "109.95 B"
453 def test_default_formatting_tb_to_kb(self
):
454 size
= disk
.Size(tb
=0.00000001)
456 assert result
== "10.74 KB"
458 def test_default_formatting_tb_to_mb(self
):
459 size
= disk
.Size(tb
=0.000001)
461 assert result
== "1.05 MB"
463 def test_default_formatting_tb_to_gb(self
):
464 size
= disk
.Size(tb
=0.001)
466 assert result
== "1.02 GB"
468 def test_default_formatting_tb_to_tb(self
):
469 size
= disk
.Size(tb
=10)
471 assert result
== "10.00 TB"
474 class TestSizeSpecificFormatting(object):
476 def test_formatting_b(self
):
477 size
= disk
.Size(b
=2048)
478 result
= "%s" % size
.b
479 assert "%s" % size
.b
== "%s" % size
.bytes
480 assert result
== "2048.00 B"
482 def test_formatting_kb(self
):
483 size
= disk
.Size(kb
=5700)
484 result
= "%s" % size
.kb
485 assert "%s" % size
.kb
== "%s" % size
.kilobytes
486 assert result
== "5700.00 KB"
488 def test_formatting_mb(self
):
489 size
= disk
.Size(mb
=4000)
490 result
= "%s" % size
.mb
491 assert "%s" % size
.mb
== "%s" % size
.megabytes
492 assert result
== "4000.00 MB"
494 def test_formatting_gb(self
):
495 size
= disk
.Size(gb
=77777)
496 result
= "%s" % size
.gb
497 assert "%s" % size
.gb
== "%s" % size
.gigabytes
498 assert result
== "77777.00 GB"
500 def test_formatting_tb(self
):
501 size
= disk
.Size(tb
=1027)
502 result
= "%s" % size
.tb
503 assert "%s" % size
.tb
== "%s" % size
.terabytes
504 assert result
== "1027.00 TB"