]> git.proxmox.com Git - ceph.git/blame - ceph/src/ceph-volume/ceph_volume/tests/devices/lvm/test_batch.py
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / ceph-volume / ceph_volume / tests / devices / lvm / test_batch.py
CommitLineData
494da23a 1import pytest
f6b5b4d7 2import json
f91f0fd5
TL
3import random
4
5from argparse import ArgumentError
6from mock import MagicMock, patch
7
1e59de90 8from ceph_volume.api import lvm
91327a77 9from ceph_volume.devices.lvm import batch
f91f0fd5 10from ceph_volume.util import arg_validators
91327a77
AA
11
12
11fdf7f2 13class TestBatch(object):
f64942e4
AA
14
15 def test_batch_instance(self, is_root):
16 b = batch.Batch([])
17 b.main()
18
a4b75251
TL
19 def test_invalid_osd_ids_passed(self):
20 with pytest.raises(SystemExit):
21 batch.Batch(argv=['--osd-ids', '1', 'foo']).main()
22
494da23a
TL
23 def test_disjoint_device_lists(self, factory):
24 device1 = factory(used_by_ceph=False, available=True, abspath="/dev/sda")
25 device2 = factory(used_by_ceph=False, available=True, abspath="/dev/sdb")
f91f0fd5
TL
26 devices = [device1, device2]
27 db_devices = [device2]
494da23a 28 with pytest.raises(Exception) as disjoint_ex:
f91f0fd5 29 batch.ensure_disjoint_device_lists(devices, db_devices)
494da23a
TL
30 assert 'Device lists are not disjoint' in str(disjoint_ex.value)
31
f91f0fd5
TL
32 @patch('ceph_volume.util.arg_validators.Device')
33 def test_reject_partition(self, mocked_device):
34 mocked_device.return_value = MagicMock(
35 is_partition=True,
33c7a0ef
TL
36 has_fs=False,
37 is_lvm_member=False,
f91f0fd5 38 has_gpt_headers=False,
1d09f67e 39 has_partitions=False,
f91f0fd5
TL
40 )
41 with pytest.raises(ArgumentError):
42 arg_validators.ValidBatchDevice()('foo')
f64942e4 43
f91f0fd5
TL
44 @pytest.mark.parametrize('format_', ['pretty', 'json', 'json-pretty'])
45 def test_report(self, format_, factory, conf_ceph_stub, mock_device_generator):
46 # just ensure reporting works
47 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
48 devs = [mock_device_generator() for _ in range(5)]
49 args = factory(data_slots=1,
50 osds_per_device=1,
51 osd_ids=[],
52 report=True,
53 format=format_,
54 devices=devs,
55 db_devices=[],
56 wal_devices=[],
57 bluestore=True,
58 block_db_size="1G",
59 dmcrypt=True,
20effc67 60 data_allocate_fraction=1.0,
f91f0fd5
TL
61 )
62 b = batch.Batch([])
63 plan = b.get_plan(args)
64 b.args = args
65 b.report(plan)
91327a77 66
f91f0fd5
TL
67 @pytest.mark.parametrize('format_', ['json', 'json-pretty'])
68 def test_json_report_valid_empty(self, format_, factory, conf_ceph_stub, mock_device_generator):
69 # ensure json reports are valid when empty
70 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
71 devs = []
72 args = factory(data_slots=1,
73 osds_per_device=1,
74 osd_ids=[],
75 report=True,
76 format=format_,
77 devices=devs,
78 db_devices=[],
79 wal_devices=[],
80 bluestore=True,
81 block_db_size="1G",
82 dmcrypt=True,
20effc67 83 data_allocate_fraction=1.0,
f91f0fd5
TL
84 )
85 b = batch.Batch([])
86 plan = b.get_plan(args)
87 b.args = args
88 report = b._create_report(plan)
89 json.loads(report)
91327a77 90
f91f0fd5
TL
91 @pytest.mark.parametrize('format_', ['json', 'json-pretty'])
92 def test_json_report_valid_empty_unavailable_fast(self, format_, factory, conf_ceph_stub, mock_device_generator):
93 # ensure json reports are valid when empty
94 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
95 devs = [mock_device_generator() for _ in range(5)]
96 fast_devs = [mock_device_generator()]
97 fast_devs[0].available_lvm = False
98 args = factory(data_slots=1,
99 osds_per_device=1,
100 osd_ids=[],
101 report=True,
102 format=format_,
103 devices=devs,
104 db_devices=fast_devs,
105 wal_devices=[],
106 bluestore=True,
107 block_db_size="1G",
108 dmcrypt=True,
20effc67 109 data_allocate_fraction=1.0,
f91f0fd5 110 )
92f5a8d4 111 b = batch.Batch([])
f91f0fd5 112 plan = b.get_plan(args)
92f5a8d4 113 b.args = args
f91f0fd5
TL
114 report = b._create_report(plan)
115 json.loads(report)
116
117
118 @pytest.mark.parametrize('format_', ['json', 'json-pretty'])
119 def test_json_report_valid_empty_unavailable_very_fast(self, format_, factory, conf_ceph_stub, mock_device_generator):
120 # ensure json reports are valid when empty
121 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
122 devs = [mock_device_generator() for _ in range(5)]
123 fast_devs = [mock_device_generator()]
124 very_fast_devs = [mock_device_generator()]
125 very_fast_devs[0].available_lvm = False
126 args = factory(data_slots=1,
127 osds_per_device=1,
128 osd_ids=[],
129 report=True,
130 format=format_,
131 devices=devs,
132 db_devices=fast_devs,
133 wal_devices=very_fast_devs,
134 bluestore=True,
135 block_db_size="1G",
136 dmcrypt=True,
20effc67 137 data_allocate_fraction=1.0,
f91f0fd5
TL
138 )
139 b = batch.Batch([])
140 plan = b.get_plan(args)
141 b.args = args
142 report = b._create_report(plan)
143 json.loads(report)
144
145 @pytest.mark.parametrize('rota', [0, 1])
146 def test_batch_sort_full(self, factory, rota):
147 device1 = factory(used_by_ceph=False, available=True, rotational=rota, abspath="/dev/sda")
148 device2 = factory(used_by_ceph=False, available=True, rotational=rota, abspath="/dev/sdb")
149 device3 = factory(used_by_ceph=False, available=True, rotational=rota, abspath="/dev/sdc")
150 devices = [device1, device2, device3]
151 args = factory(report=True,
152 devices=devices,
f91f0fd5 153 )
f6b5b4d7
TL
154 b = batch.Batch([])
155 b.args = args
f91f0fd5
TL
156 b._sort_rotational_disks()
157 assert len(b.args.devices) == 3
158
05a536ef 159 @pytest.mark.parametrize('objectstore', ['bluestore'])
f91f0fd5
TL
160 def test_batch_sort_mixed(self, factory, objectstore):
161 device1 = factory(used_by_ceph=False, available=True, rotational=1, abspath="/dev/sda")
162 device2 = factory(used_by_ceph=False, available=True, rotational=1, abspath="/dev/sdb")
163 device3 = factory(used_by_ceph=False, available=True, rotational=0, abspath="/dev/sdc")
164 devices = [device1, device2, device3]
165 args = factory(report=True,
166 devices=devices,
f91f0fd5
TL
167 )
168 b = batch.Batch([])
169 b.args = args
170 b._sort_rotational_disks()
171 assert len(b.args.devices) == 2
05a536ef 172 assert len(b.args.db_devices) == 1
f91f0fd5
TL
173
174 def test_get_physical_osds_return_len(self, factory,
175 mock_devices_available,
176 conf_ceph_stub,
177 osds_per_device):
178 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
179 args = factory(data_slots=1, osds_per_device=osds_per_device,
20effc67
TL
180 osd_ids=[], dmcrypt=False,
181 data_allocate_fraction=1.0)
f91f0fd5
TL
182 osds = batch.get_physical_osds(mock_devices_available, args)
183 assert len(osds) == len(mock_devices_available) * osds_per_device
184
185 def test_get_physical_osds_rel_size(self, factory,
186 mock_devices_available,
187 conf_ceph_stub,
20effc67
TL
188 osds_per_device,
189 data_allocate_fraction):
f91f0fd5 190 args = factory(data_slots=1, osds_per_device=osds_per_device,
20effc67
TL
191 osd_ids=[], dmcrypt=False,
192 data_allocate_fraction=data_allocate_fraction)
f91f0fd5
TL
193 osds = batch.get_physical_osds(mock_devices_available, args)
194 for osd in osds:
20effc67 195 assert osd.data[1] == data_allocate_fraction / osds_per_device
f91f0fd5
TL
196
197 def test_get_physical_osds_abs_size(self, factory,
198 mock_devices_available,
199 conf_ceph_stub,
20effc67
TL
200 osds_per_device,
201 data_allocate_fraction):
f91f0fd5
TL
202 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
203 args = factory(data_slots=1, osds_per_device=osds_per_device,
20effc67
TL
204 osd_ids=[], dmcrypt=False,
205 data_allocate_fraction=data_allocate_fraction)
f91f0fd5
TL
206 osds = batch.get_physical_osds(mock_devices_available, args)
207 for osd, dev in zip(osds, mock_devices_available):
20effc67 208 assert osd.data[2] == int(dev.vg_size[0] * (data_allocate_fraction / osds_per_device))
f91f0fd5
TL
209
210 def test_get_physical_osds_osd_ids(self, factory,
211 mock_devices_available,
212 osds_per_device):
213 pass
214
215 def test_get_physical_fast_allocs_length(self, factory,
216 conf_ceph_stub,
217 mock_devices_available):
218 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
219 args = factory(block_db_slots=None, get_block_db_size=None)
220 fast = batch.get_physical_fast_allocs(mock_devices_available,
221 'block_db', 2, 2, args)
222 assert len(fast) == 2
223
2a845540
TL
224 def test_get_physical_fast_allocs_abs_size(self, factory,
225 conf_ceph_stub,
226 mock_devices_available):
227 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
228 args = factory(block_db_slots=None, get_block_db_size=None)
229 fasts = batch.get_physical_fast_allocs(mock_devices_available,
230 'block_db', 2, 2, args)
231 for fast, dev in zip(fasts, mock_devices_available):
232 assert fast[2] == int(dev.vg_size[0] / 2)
233
1e59de90
TL
234 def test_get_physical_fast_allocs_abs_size_unused_devs(self, factory,
235 conf_ceph_stub,
236 mock_devices_available):
237 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
238 args = factory(block_db_slots=None, get_block_db_size=None)
239 dev_size = 21474836480
240 vg_size = dev_size
241 for dev in mock_devices_available:
242 dev.vg_name = None
243 dev.vg_size = [vg_size]
244 dev.vg_free = dev.vg_size
245 dev.vgs = []
246 slots_per_device = 2
247 fasts = batch.get_physical_fast_allocs(mock_devices_available,
248 'block_db', slots_per_device, 2, args)
249 expected_slot_size = int(dev_size / slots_per_device)
250 for (_, _, slot_size, _) in fasts:
251 assert slot_size == expected_slot_size
252
253 def test_get_physical_fast_allocs_abs_size_multi_pvs_per_vg(self, factory,
254 conf_ceph_stub,
255 mock_devices_available):
256 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
257 args = factory(block_db_slots=None, get_block_db_size=None)
258 dev_size = 21474836480
259 num_devices = len(mock_devices_available)
260 vg_size = dev_size * num_devices
261 vg_name = 'vg_foo'
262 for dev in mock_devices_available:
263 dev.vg_name = vg_name
264 dev.vg_size = [vg_size]
265 dev.vg_free = dev.vg_size
266 dev.vgs = [lvm.VolumeGroup(vg_name=dev.vg_name, lv_name=dev.lv_name)]
267 slots_per_device = 2
268 slots_per_vg = slots_per_device * num_devices
269 fasts = batch.get_physical_fast_allocs(mock_devices_available,
270 'block_db', slots_per_device, 2, args)
271 expected_slot_size = int(vg_size / slots_per_vg)
272 for (_, _, slot_size, _) in fasts:
273 assert slot_size == expected_slot_size
274
522d829b
TL
275 def test_batch_fast_allocations_one_block_db_length(self, factory, conf_ceph_stub,
276 mock_lv_device_generator):
277 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
278
279 b = batch.Batch([])
280 db_lv_devices = [mock_lv_device_generator()]
281 fast = b.fast_allocations(db_lv_devices, 1, 0, 'block_db')
282 assert len(fast) == 1
283
f91f0fd5
TL
284 @pytest.mark.parametrize('occupied_prior', range(7))
285 @pytest.mark.parametrize('slots,num_devs',
286 [l for sub in [list(zip([x]*x, range(1, x + 1))) for x in range(1,7)] for l in sub])
287 def test_get_physical_fast_allocs_length_existing(self,
288 num_devs,
289 slots,
290 occupied_prior,
291 factory,
292 conf_ceph_stub,
293 mock_device_generator):
294 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
295 occupied_prior = min(occupied_prior, slots)
296 devs = [mock_device_generator() for _ in range(num_devs)]
297 already_assigned = 0
298 while already_assigned < occupied_prior:
299 dev_i = random.randint(0, num_devs - 1)
300 dev = devs[dev_i]
301 if len(dev.lvs) < occupied_prior:
302 dev.lvs.append('foo')
303 dev.path = '/dev/bar'
304 already_assigned = sum([len(d.lvs) for d in devs])
305 args = factory(block_db_slots=None, get_block_db_size=None)
306 expected_num_osds = max(len(devs) * slots - occupied_prior, 0)
307 fast = batch.get_physical_fast_allocs(devs,
308 'block_db', slots,
309 expected_num_osds, args)
310 assert len(fast) == expected_num_osds
311 expected_assignment_on_used_devices = sum([slots - len(d.lvs) for d in devs if len(d.lvs) > 0])
312 assert len([f for f in fast if f[0] == '/dev/bar']) == expected_assignment_on_used_devices
313 assert len([f for f in fast if f[0] != '/dev/bar']) == expected_num_osds - expected_assignment_on_used_devices
314
315 def test_get_lvm_osds_return_len(self, factory,
316 mock_lv_device_generator,
317 conf_ceph_stub,
318 osds_per_device):
319 conf_ceph_stub('[global]\nfsid=asdf-lkjh')
320 args = factory(data_slots=1, osds_per_device=osds_per_device,
321 osd_ids=[], dmcrypt=False)
322 mock_lvs = [mock_lv_device_generator()]
323 osds = batch.get_lvm_osds(mock_lvs, args)
324 assert len(osds) == 1
325
326
327class TestBatchOsd(object):
328
329 def test_osd_class_ctor(self):
330 osd = batch.Batch.OSD('/dev/data', 1, '5G', 1, 1, None)
331 assert osd.data == batch.Batch.OSD.VolSpec('/dev/data',
332 1,
333 '5G',
334 1,
335 'data')
336 def test_add_fast(self):
337 osd = batch.Batch.OSD('/dev/data', 1, '5G', 1, 1, None)
338 osd.add_fast_device('/dev/db', 1, '5G', 1, 'block_db')
339 assert osd.fast == batch.Batch.OSD.VolSpec('/dev/db',
340 1,
341 '5G',
342 1,
343 'block_db')
344
345 def test_add_very_fast(self):
346 osd = batch.Batch.OSD('/dev/data', 1, '5G', 1, 1, None)
347 osd.add_very_fast_device('/dev/wal', 1, '5G', 1)
348 assert osd.very_fast == batch.Batch.OSD.VolSpec('/dev/wal',
349 1,
350 '5G',
351 1,
352 'block_wal')