]>
Commit | Line | Data |
---|---|---|
c07f9fc5 | 1 | #!/usr/bin/env python |
7c673cae FG |
2 | # |
3 | # Copyright (C) 2015, 2016 Red Hat <contact@redhat.com> | |
4 | # | |
5 | # This program is free software; you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Library Public License as published by | |
7 | # the Free Software Foundation; either version 2, or (at your option) | |
8 | # any later version. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU Library Public License for more details. | |
14 | # | |
15 | from mock import patch, DEFAULT | |
16 | import os | |
17 | import platform | |
18 | import io | |
19 | import shutil | |
20 | import subprocess | |
21 | import tempfile | |
22 | import unittest | |
23 | from ceph_disk import main | |
24 | ||
25 | try: | |
26 | import builtins | |
27 | except: | |
28 | import __builtin__ as builtins | |
29 | ||
30 | ||
31 | def fail_to_mount(dev, fstype, options): | |
32 | raise main.MountError(dev + " mount fail") | |
33 | ||
34 | ||
35 | class TestCephDisk(object): | |
36 | ||
37 | def setup_class(self): | |
38 | main.setup_logging(verbose=True, log_stdout=False) | |
39 | ||
40 | def test_main_list_json(self, capsys): | |
41 | if platform.system() == "FreeBSD": | |
42 | return | |
43 | ||
44 | data = tempfile.mkdtemp() | |
45 | main.setup_statedir(data) | |
46 | args = main.parse_args(['list', '--format', 'json']) | |
47 | with patch.multiple( | |
48 | main, | |
49 | list_devices=lambda: {}): | |
50 | main.main_list(args) | |
51 | out, err = capsys.readouterr() | |
52 | assert '{}\n' == out | |
53 | shutil.rmtree(data) | |
54 | ||
55 | def test_main_list_plain(self, capsys): | |
56 | if platform.system() == "FreeBSD": | |
57 | return | |
58 | ||
59 | data = tempfile.mkdtemp() | |
60 | main.setup_statedir(data) | |
61 | args = main.parse_args(['list']) | |
62 | with patch.multiple( | |
63 | main, | |
64 | list_devices=lambda: {}): | |
65 | main.main_list(args) | |
66 | out, err = capsys.readouterr() | |
67 | assert '' == out | |
68 | shutil.rmtree(data) | |
69 | ||
70 | def test_list_format_more_osd_info_plain(self): | |
71 | dev = { | |
72 | 'ceph_fsid': 'UUID', | |
73 | 'cluster': 'ceph', | |
74 | 'whoami': '1234', | |
75 | 'journal_dev': '/dev/Xda2', | |
76 | } | |
77 | out = main.list_format_more_osd_info_plain(dev) | |
78 | assert dev['cluster'] in " ".join(out) | |
79 | assert dev['journal_dev'] in " ".join(out) | |
80 | assert dev['whoami'] in " ".join(out) | |
81 | ||
82 | dev = { | |
83 | 'ceph_fsid': 'UUID', | |
84 | 'whoami': '1234', | |
85 | 'journal_dev': '/dev/Xda2', | |
86 | } | |
87 | out = main.list_format_more_osd_info_plain(dev) | |
88 | assert 'unknown cluster' in " ".join(out) | |
89 | ||
90 | def test_list_format_plain(self): | |
91 | payload = [{ | |
92 | 'path': '/dev/Xda', | |
93 | 'ptype': 'unknown', | |
94 | 'type': 'other', | |
95 | 'mount': '/somewhere', | |
96 | }] | |
97 | out = main.list_format_plain(payload) | |
98 | assert payload[0]['path'] in out | |
99 | assert payload[0]['type'] in out | |
100 | assert payload[0]['mount'] in out | |
101 | ||
102 | payload = [{ | |
103 | 'path': '/dev/Xda1', | |
104 | 'ptype': 'unknown', | |
105 | 'type': 'swap', | |
106 | }] | |
107 | out = main.list_format_plain(payload) | |
108 | assert payload[0]['path'] in out | |
109 | assert payload[0]['type'] in out | |
110 | ||
111 | payload = [{ | |
112 | 'path': '/dev/Xda', | |
113 | 'partitions': [ | |
114 | { | |
115 | 'dmcrypt': {}, | |
116 | 'ptype': 'whatever', | |
117 | 'is_partition': True, | |
118 | 'fs_type': 'ext4', | |
119 | 'path': '/dev/Xda1', | |
120 | 'mounted': '/somewhere', | |
121 | 'type': 'other', | |
122 | } | |
123 | ], | |
124 | }] | |
125 | out = main.list_format_plain(payload) | |
126 | assert payload[0]['path'] in out | |
127 | assert payload[0]['partitions'][0]['path'] in out | |
128 | ||
129 | def test_list_format_dev_plain(dev): | |
130 | # | |
131 | # data | |
132 | # | |
133 | dev = { | |
134 | 'path': '/dev/Xda1', | |
135 | 'ptype': main.PTYPE['regular']['osd']['ready'], | |
136 | 'state': 'prepared', | |
137 | 'whoami': '1234', | |
138 | } | |
139 | out = main.list_format_dev_plain(dev) | |
140 | assert 'data' in out | |
141 | assert dev['whoami'] in out | |
142 | assert dev['state'] in out | |
143 | # | |
144 | # journal | |
145 | # | |
146 | dev = { | |
147 | 'path': '/dev/Xda2', | |
148 | 'ptype': main.PTYPE['regular']['journal']['ready'], | |
149 | 'journal_for': '/dev/Xda1', | |
150 | } | |
151 | out = main.list_format_dev_plain(dev) | |
152 | assert 'journal' in out | |
153 | assert dev['journal_for'] in out | |
154 | ||
155 | # | |
156 | # dmcrypt data | |
157 | # | |
158 | ptype2type = { | |
159 | main.PTYPE['plain']['osd']['ready']: 'plain', | |
160 | main.PTYPE['luks']['osd']['ready']: 'luks', | |
161 | } | |
162 | for (ptype, type) in ptype2type.items(): | |
163 | for holders in ((), ("dm_0",), ("dm_0", "dm_1")): | |
164 | dev = { | |
165 | 'dmcrypt': { | |
166 | 'holders': holders, | |
167 | 'type': type, | |
168 | }, | |
169 | 'path': '/dev/Xda1', | |
170 | 'ptype': ptype, | |
171 | 'state': 'prepared', | |
172 | 'whoami': '1234', | |
173 | } | |
174 | out = main.list_format_dev_plain(dev) | |
175 | assert 'data' in out | |
176 | assert 'dmcrypt' in out | |
177 | assert type in out | |
178 | if len(holders) == 1: | |
179 | assert dev['whoami'] in out | |
180 | for holder in holders: | |
181 | assert holder in out | |
182 | ||
183 | # | |
184 | # dmcrypt journal | |
185 | # | |
186 | ptype2type = { | |
187 | main.PTYPE['plain']['journal']['ready']: 'plain', | |
188 | main.PTYPE['luks']['journal']['ready']: 'luks', | |
189 | } | |
190 | for (ptype, type) in ptype2type.items(): | |
191 | for holders in ((), ("dm_0",)): | |
192 | dev = { | |
193 | 'path': '/dev/Xda2', | |
194 | 'ptype': ptype, | |
195 | 'journal_for': '/dev/Xda1', | |
196 | 'dmcrypt': { | |
197 | 'holders': holders, | |
198 | 'type': type, | |
199 | }, | |
200 | } | |
201 | out = main.list_format_dev_plain(dev) | |
202 | assert 'journal' in out | |
203 | assert 'dmcrypt' in out | |
204 | assert type in out | |
205 | assert dev['journal_for'] in out | |
206 | if len(holders) == 1: | |
207 | assert holders[0] in out | |
208 | ||
209 | def test_list_dev_osd(self): | |
210 | dev = "Xda" | |
211 | mount_path = '/mount/path' | |
212 | fs_type = 'ext4' | |
213 | cluster = 'ceph' | |
214 | uuid_map = {} | |
215 | ||
216 | def more_osd_info(path, uuid_map, desc): | |
217 | desc['cluster'] = cluster | |
218 | # | |
219 | # mounted therefore active | |
220 | # | |
221 | with patch.multiple( | |
222 | main, | |
223 | is_mounted=lambda dev: mount_path, | |
224 | get_dev_fs=lambda dev: fs_type, | |
225 | more_osd_info=more_osd_info | |
226 | ): | |
227 | desc = {} | |
228 | main.list_dev_osd(dev, uuid_map, desc) | |
229 | assert {'cluster': 'ceph', | |
230 | 'fs_type': 'ext4', | |
231 | 'mount': '/mount/path', | |
232 | 'state': 'active'} == desc | |
233 | # | |
234 | # not mounted and cannot mount: unprepared | |
235 | # | |
236 | mount_path = None | |
237 | with patch.multiple( | |
238 | main, | |
239 | is_mounted=lambda dev: mount_path, | |
240 | get_dev_fs=lambda dev: fs_type, | |
241 | mount=fail_to_mount, | |
242 | more_osd_info=more_osd_info | |
243 | ): | |
244 | desc = {} | |
245 | main.list_dev_osd(dev, uuid_map, desc) | |
246 | assert {'fs_type': 'ext4', | |
247 | 'mount': mount_path, | |
248 | 'state': 'unprepared'} == desc | |
249 | # | |
250 | # not mounted and magic found: prepared | |
251 | # | |
252 | ||
253 | def get_oneliner(path, what): | |
254 | if what == 'magic': | |
255 | return main.CEPH_OSD_ONDISK_MAGIC | |
256 | else: | |
257 | raise Exception('unknown ' + what) | |
258 | with patch.multiple( | |
259 | main, | |
260 | is_mounted=lambda dev: mount_path, | |
261 | get_dev_fs=lambda dev: fs_type, | |
262 | mount=DEFAULT, | |
263 | unmount=DEFAULT, | |
264 | get_oneliner=get_oneliner, | |
265 | more_osd_info=more_osd_info | |
266 | ): | |
267 | desc = {} | |
268 | main.list_dev_osd(dev, uuid_map, desc) | |
269 | assert {'cluster': 'ceph', | |
270 | 'fs_type': 'ext4', | |
271 | 'mount': mount_path, | |
272 | 'magic': main.CEPH_OSD_ONDISK_MAGIC, | |
273 | 'state': 'prepared'} == desc | |
274 | ||
275 | def test_list_all_partitions(self): | |
276 | if platform.system() == "FreeBSD": | |
277 | return | |
278 | ||
279 | disk = "Xda" | |
280 | partition = "Xda1" | |
281 | ||
282 | with patch( | |
283 | 'ceph_disk.main.os', | |
284 | listdir=lambda path: [disk], | |
285 | ), patch.multiple( | |
286 | main, | |
287 | list_partitions=lambda dev: [partition], | |
288 | ): | |
289 | assert {disk: [partition]} == main.list_all_partitions() | |
290 | ||
291 | def test_list_data(self): | |
292 | # | |
293 | # a data partition that fails to mount is silently | |
294 | # ignored | |
295 | # | |
296 | if platform.system() == "FreeBSD": | |
297 | return | |
298 | ||
299 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
300 | disk = "Xda" | |
301 | partition = "Xda1" | |
302 | fs_type = "ext4" | |
303 | ||
304 | def get_partition_type(dev): | |
305 | return main.PTYPE['regular']['osd']['ready'] | |
306 | with patch.multiple( | |
307 | main, | |
308 | list_all_partitions=lambda: {disk: [partition]}, | |
309 | get_partition_uuid=lambda dev: partition_uuid, | |
310 | get_partition_type=get_partition_type, | |
311 | get_dev_fs=lambda dev: fs_type, | |
312 | mount=fail_to_mount, | |
313 | unmount=DEFAULT, | |
314 | is_partition=lambda dev: True, | |
315 | ): | |
316 | expect = [{'path': '/dev/' + disk, | |
317 | 'partitions': [{ | |
318 | 'dmcrypt': {}, | |
319 | 'fs_type': fs_type, | |
320 | 'is_partition': True, | |
321 | 'mount': None, | |
322 | 'path': '/dev/' + partition, | |
323 | 'ptype': main.PTYPE['regular']['osd']['ready'], | |
324 | 'state': 'unprepared', | |
325 | 'type': 'data', | |
326 | 'uuid': partition_uuid, | |
327 | }]}] | |
328 | assert expect == main.list_devices() | |
329 | ||
330 | def test_list_dmcrypt_data(self): | |
331 | if platform.system() == "FreeBSD": | |
332 | return | |
333 | ||
334 | partition_type2type = { | |
335 | main.PTYPE['plain']['osd']['ready']: 'plain', | |
336 | main.PTYPE['luks']['osd']['ready']: 'LUKS', | |
337 | } | |
338 | for (partition_type, type) in partition_type2type.items(): | |
339 | # | |
340 | # dmcrypt data partition with one holder | |
341 | # | |
342 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
343 | disk = "Xda" | |
344 | partition = "Xda1" | |
345 | holders = ["dm-dummy"] | |
346 | with patch.multiple( | |
347 | main, | |
348 | is_held=lambda dev: holders, | |
349 | list_all_partitions=lambda: {disk: [partition]}, | |
350 | get_partition_uuid=lambda dev: partition_uuid, | |
351 | get_partition_type=lambda dev: partition_type, | |
352 | is_partition=lambda dev: True, | |
353 | ): | |
354 | expect = [{'path': '/dev/' + disk, | |
355 | 'partitions': [{ | |
356 | 'dmcrypt': { | |
357 | 'holders': holders, | |
358 | 'type': type, | |
359 | }, | |
360 | 'fs_type': None, | |
361 | 'is_partition': True, | |
362 | 'mount': None, | |
363 | 'path': '/dev/' + partition, | |
364 | 'ptype': partition_type, | |
365 | 'state': 'unprepared', | |
366 | 'type': 'data', | |
367 | 'uuid': partition_uuid, | |
368 | }]}] | |
369 | assert expect == main.list_devices() | |
370 | # | |
371 | # dmcrypt data partition with two holders | |
372 | # | |
373 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
374 | disk = "Xda" | |
375 | partition = "Xda1" | |
376 | holders = ["dm-dummy", "dm-dummy1"] | |
377 | with patch.multiple( | |
378 | main, | |
379 | is_held=lambda dev: holders, | |
380 | list_all_partitions=lambda: {disk: [partition]}, | |
381 | get_partition_uuid=lambda dev: partition_uuid, | |
382 | get_partition_type=lambda dev: partition_type, | |
383 | is_partition=lambda dev: True, | |
384 | ): | |
385 | expect = [{'path': '/dev/' + disk, | |
386 | 'partitions': [{ | |
387 | 'dmcrypt': { | |
388 | 'holders': holders, | |
389 | 'type': type, | |
390 | }, | |
391 | 'is_partition': True, | |
392 | 'path': '/dev/' + partition, | |
393 | 'ptype': partition_type, | |
394 | 'type': 'data', | |
395 | 'uuid': partition_uuid, | |
396 | }]}] | |
397 | assert expect == main.list_devices() | |
398 | ||
399 | def test_list_multipath(self): | |
400 | # | |
401 | # multipath data partition | |
402 | # | |
403 | if platform.system() == "FreeBSD": | |
404 | return | |
405 | ||
406 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
407 | disk = "Xda" | |
408 | partition = "Xda1" | |
409 | ||
410 | def get_partition_type(dev): | |
411 | return main.PTYPE['mpath']['osd']['ready'] | |
412 | with patch.multiple( | |
413 | main, | |
414 | list_all_partitions=lambda: {disk: [partition]}, | |
415 | get_partition_uuid=lambda dev: partition_uuid, | |
416 | get_partition_type=get_partition_type, | |
417 | is_partition=lambda dev: True, | |
418 | ): | |
419 | expect = [{'path': '/dev/' + disk, | |
420 | 'partitions': [{ | |
421 | 'dmcrypt': {}, | |
422 | 'fs_type': None, | |
423 | 'is_partition': True, | |
424 | 'mount': None, | |
425 | 'multipath': True, | |
426 | 'path': '/dev/' + partition, | |
427 | 'ptype': main.PTYPE['mpath']['osd']['ready'], | |
428 | 'state': 'unprepared', | |
429 | 'type': 'data', | |
430 | 'uuid': partition_uuid, | |
431 | }]}] | |
432 | assert expect == main.list_devices() | |
433 | # | |
434 | # multipath journal partition | |
435 | # | |
436 | journal_partition_uuid = "2cc40457-259e-4542-b029-785c7cc37871" | |
437 | ||
438 | def get_partition_type(dev): | |
439 | return main.PTYPE['mpath']['journal']['ready'] | |
440 | with patch.multiple( | |
441 | main, | |
442 | list_all_partitions=lambda: {disk: [partition]}, | |
443 | get_partition_uuid=lambda dev: journal_partition_uuid, | |
444 | get_partition_type=get_partition_type, | |
445 | is_partition=lambda dev: True, | |
446 | ): | |
447 | expect = [{'path': '/dev/' + disk, | |
448 | 'partitions': [{ | |
449 | 'dmcrypt': {}, | |
450 | 'is_partition': True, | |
451 | 'multipath': True, | |
452 | 'path': '/dev/' + partition, | |
453 | 'ptype': main.PTYPE['mpath']['journal']['ready'], | |
454 | 'type': 'journal', | |
455 | 'uuid': journal_partition_uuid, | |
456 | }]}] | |
457 | assert expect == main.list_devices() | |
458 | ||
459 | def test_list_default(self): | |
460 | self.list(main.PTYPE['plain']['osd']['ready'], | |
461 | main.PTYPE['plain']['journal']['ready']) | |
462 | self.list(main.PTYPE['luks']['osd']['ready'], | |
463 | main.PTYPE['luks']['journal']['ready']) | |
464 | self.list(main.PTYPE['regular']['osd']['ready'], | |
465 | main.PTYPE['regular']['journal']['ready']) | |
466 | ||
467 | def test_list_bluestore(self): | |
468 | if platform.system() == "FreeBSD": | |
469 | return | |
470 | ||
471 | self.list(main.PTYPE['plain']['osd']['ready'], | |
472 | main.PTYPE['plain']['block']['ready']) | |
473 | self.list(main.PTYPE['luks']['osd']['ready'], | |
474 | main.PTYPE['luks']['block']['ready']) | |
475 | self.list(main.PTYPE['regular']['osd']['ready'], | |
476 | main.PTYPE['regular']['block']['ready']) | |
477 | ||
478 | def list(self, data_ptype, space_ptype): | |
479 | # | |
480 | # a single disk has a data partition and a journal | |
481 | # partition and the osd is active | |
482 | # | |
483 | name = main.Ptype.space_ptype_to_name(space_ptype) | |
484 | data_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
485 | disk = "Xda" | |
486 | data = "Xda1" | |
487 | data_holder = "dm-dummy" | |
488 | space = "Xda2" | |
489 | space_holder = "dm-dummy" | |
490 | mount_path = '/mount/path' | |
491 | fs_type = 'ext4' | |
492 | space_uuid = "7ad5e65a-0ca5-40e4-a896-62a74ca61c55" | |
493 | ceph_fsid = "60a2ef70-d99b-4b9b-a83c-8a86e5e60091" | |
494 | osd_id = '1234' | |
495 | ||
496 | def get_oneliner(path, what): | |
497 | if '_uuid' in what: | |
498 | if what == name + '_uuid': | |
499 | return space_uuid | |
500 | else: | |
501 | return None | |
502 | elif what == 'ceph_fsid': | |
503 | return ceph_fsid | |
504 | elif what == 'whoami': | |
505 | return osd_id | |
506 | else: | |
507 | raise Exception('unknown ' + what) | |
508 | ||
509 | def get_partition_uuid(dev): | |
510 | if dev == '/dev/' + data: | |
511 | return data_uuid | |
512 | elif dev == '/dev/' + space: | |
513 | return space_uuid | |
514 | else: | |
515 | raise Exception('unknown ' + dev) | |
516 | ||
517 | def get_partition_type(dev): | |
518 | if (dev == '/dev/' + data or | |
519 | dev == '/dev/' + data_holder): | |
520 | return data_ptype | |
521 | elif (dev == '/dev/' + space or | |
522 | dev == '/dev/' + space_holder): | |
523 | return space_ptype | |
524 | else: | |
525 | raise Exception('unknown ' + dev) | |
526 | cluster = 'ceph' | |
527 | if data_ptype == main.PTYPE['regular']['osd']['ready']: | |
528 | data_dmcrypt = {} | |
529 | elif data_ptype == main.PTYPE['plain']['osd']['ready']: | |
530 | data_dmcrypt = { | |
531 | 'type': 'plain', | |
532 | 'holders': [data_holder], | |
533 | } | |
534 | elif data_ptype == main.PTYPE['luks']['osd']['ready']: | |
535 | data_dmcrypt = { | |
536 | 'type': 'LUKS', | |
537 | 'holders': [data_holder], | |
538 | } | |
539 | else: | |
540 | raise Exception('unknown ' + data_ptype) | |
541 | ||
542 | if space_ptype == main.PTYPE['regular'][name]['ready']: | |
543 | space_dmcrypt = {} | |
544 | elif space_ptype == main.PTYPE['plain'][name]['ready']: | |
545 | space_dmcrypt = { | |
546 | 'type': 'plain', | |
547 | 'holders': [space_holder], | |
548 | } | |
549 | elif space_ptype == main.PTYPE['luks'][name]['ready']: | |
550 | space_dmcrypt = { | |
551 | 'type': 'LUKS', | |
552 | 'holders': [space_holder], | |
553 | } | |
554 | else: | |
555 | raise Exception('unknown ' + space_ptype) | |
556 | ||
557 | if data_dmcrypt: | |
558 | def is_held(dev): | |
559 | if dev == '/dev/' + data: | |
560 | return [data_holder] | |
561 | elif dev == '/dev/' + space: | |
562 | return [space_holder] | |
563 | else: | |
564 | raise Exception('unknown ' + dev) | |
565 | else: | |
566 | def is_held(dev): | |
567 | return [] | |
568 | ||
569 | with patch.multiple( | |
570 | main, | |
571 | list_all_partitions=lambda: {disk: [data, space]}, | |
572 | get_dev_fs=lambda dev: fs_type, | |
573 | is_mounted=lambda dev: mount_path, | |
574 | get_partition_uuid=get_partition_uuid, | |
575 | get_partition_type=get_partition_type, | |
576 | find_cluster_by_uuid=lambda ceph_fsid: cluster, | |
577 | is_partition=lambda dev: True, | |
578 | mount=DEFAULT, | |
579 | unmount=DEFAULT, | |
580 | get_oneliner=get_oneliner, | |
581 | is_held=is_held, | |
582 | ): | |
583 | expect = [{'path': '/dev/' + disk, | |
584 | 'partitions': [{ | |
585 | 'ceph_fsid': ceph_fsid, | |
586 | 'cluster': cluster, | |
587 | 'dmcrypt': data_dmcrypt, | |
588 | 'fs_type': fs_type, | |
589 | 'is_partition': True, | |
590 | name + '_dev': '/dev/' + space, | |
591 | name + '_uuid': space_uuid, | |
592 | 'mount': mount_path, | |
593 | 'path': '/dev/' + data, | |
594 | 'ptype': data_ptype, | |
595 | 'state': 'active', | |
596 | 'type': 'data', | |
597 | 'whoami': osd_id, | |
598 | 'uuid': data_uuid, | |
599 | }, { | |
600 | 'dmcrypt': space_dmcrypt, | |
601 | 'is_partition': True, | |
602 | name + '_for': '/dev/' + data, | |
603 | 'path': '/dev/' + space, | |
604 | 'ptype': space_ptype, | |
605 | 'type': name, | |
606 | 'uuid': space_uuid, | |
607 | }]}] | |
608 | assert expect == main.list_devices() | |
609 | ||
610 | def test_list_other(self): | |
611 | # | |
612 | # not swap, unknown fs type, not mounted, with uuid | |
613 | # | |
614 | if platform.system() == "FreeBSD": | |
615 | return | |
616 | ||
617 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
618 | partition_type = "e51adfb9-e9fd-4718-9fc1-7a0cb03ea3f4" | |
619 | disk = "Xda" | |
620 | partition = "Xda1" | |
621 | with patch.multiple( | |
622 | main, | |
623 | list_all_partitions=lambda: {disk: [partition]}, | |
624 | get_partition_uuid=lambda dev: partition_uuid, | |
625 | get_partition_type=lambda dev: partition_type, | |
626 | is_partition=lambda dev: True, | |
627 | ): | |
628 | expect = [{'path': '/dev/' + disk, | |
629 | 'partitions': [{'dmcrypt': {}, | |
630 | 'is_partition': True, | |
631 | 'path': '/dev/' + partition, | |
632 | 'ptype': partition_type, | |
633 | 'type': 'other', | |
634 | 'uuid': partition_uuid}]}] | |
635 | assert expect == main.list_devices() | |
636 | # | |
637 | # not swap, mounted, ext4 fs type, with uuid | |
638 | # | |
639 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
640 | partition_type = "e51adfb9-e9fd-4718-9fc1-7a0cb03ea3f4" | |
641 | disk = "Xda" | |
642 | partition = "Xda1" | |
643 | mount_path = '/mount/path' | |
644 | fs_type = 'ext4' | |
645 | with patch.multiple( | |
646 | main, | |
647 | list_all_partitions=lambda: {disk: [partition]}, | |
648 | get_dev_fs=lambda dev: fs_type, | |
649 | is_mounted=lambda dev: mount_path, | |
650 | get_partition_uuid=lambda dev: partition_uuid, | |
651 | get_partition_type=lambda dev: partition_type, | |
652 | is_partition=lambda dev: True, | |
653 | ): | |
654 | expect = [{'path': '/dev/' + disk, | |
655 | 'partitions': [{ | |
656 | 'dmcrypt': {}, | |
657 | 'is_partition': True, | |
658 | 'mount': mount_path, | |
659 | 'fs_type': fs_type, | |
660 | 'path': '/dev/' + partition, | |
661 | 'ptype': partition_type, | |
662 | 'type': 'other', | |
663 | 'uuid': partition_uuid, | |
664 | }]}] | |
665 | assert expect == main.list_devices() | |
666 | ||
667 | # | |
668 | # swap, with uuid | |
669 | # | |
670 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
671 | partition_type = "e51adfb9-e9fd-4718-9fc1-7a0cb03ea3f4" | |
672 | disk = "Xda" | |
673 | partition = "Xda1" | |
674 | with patch.multiple( | |
675 | main, | |
676 | list_all_partitions=lambda: {disk: [partition]}, | |
677 | is_swap=lambda dev: True, | |
678 | get_partition_uuid=lambda dev: partition_uuid, | |
679 | get_partition_type=lambda dev: partition_type, | |
680 | is_partition=lambda dev: True, | |
681 | ): | |
682 | expect = [{'path': '/dev/' + disk, | |
683 | 'partitions': [{'dmcrypt': {}, | |
684 | 'is_partition': True, | |
685 | 'path': '/dev/' + partition, | |
686 | 'ptype': partition_type, | |
687 | 'type': 'swap', | |
688 | 'uuid': partition_uuid}]}] | |
689 | assert expect == main.list_devices() | |
690 | ||
691 | # | |
692 | # whole disk | |
693 | # | |
694 | partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2" | |
695 | disk = "Xda" | |
696 | partition = "Xda1" | |
697 | with patch.multiple( | |
698 | main, | |
699 | list_all_partitions=lambda: {disk: []}, | |
700 | is_partition=lambda dev: False, | |
701 | ): | |
702 | expect = [{'path': '/dev/' + disk, | |
703 | 'dmcrypt': {}, | |
704 | 'is_partition': False, | |
705 | 'ptype': 'unknown', | |
706 | 'type': 'other'}] | |
707 | assert expect == main.list_devices() | |
708 | ||
709 | ||
710 | class TestCephDiskDeactivateAndDestroy(unittest.TestCase): | |
711 | ||
712 | def setup_class(self): | |
713 | main.setup_logging(verbose=True, log_stdout=False) | |
714 | ||
715 | @patch('{0}.open'.format(builtins.__name__)) | |
716 | def test_main_deactivate(self, mock_open): | |
717 | data = tempfile.mkdtemp() | |
718 | main.setup_statedir(data) | |
719 | DMCRYPT_LUKS_OSD_UUID = '4fbd7e29-9d25-41b8-afd0-35865ceff05d' | |
720 | part_uuid = '0ce28a16-6d5d-11e5-aec3-fa163e5c167b' | |
721 | disk = 'sdX' | |
722 | # | |
723 | # Can not find match device by osd-id | |
724 | # | |
725 | args = main.parse_args(['deactivate', | |
726 | '--cluster', 'ceph', | |
727 | '--deactivate-by-id', '5566']) | |
728 | fake_device = [{'path': '/dev/' + disk, | |
729 | 'partitions': [{ | |
730 | 'path': '/dev/sdX1', | |
731 | 'whoami': '-1', | |
732 | }]}] | |
733 | with patch.multiple( | |
734 | main, | |
735 | list_devices=lambda: fake_device, | |
736 | ): | |
737 | self.assertRaises(Exception, main.main_deactivate, args) | |
738 | ||
739 | # | |
740 | # find match device by osd-id, status: OSD_STATUS_IN_DOWN | |
741 | # with --mark-out option | |
742 | # | |
743 | args = main.parse_args(['deactivate', | |
744 | '--cluster', 'ceph', | |
745 | '--deactivate-by-id', '5566', | |
746 | '--mark-out']) | |
747 | fake_device = [{'path': '/dev/' + disk, | |
748 | 'partitions': [{ | |
749 | 'ptype': DMCRYPT_LUKS_OSD_UUID, | |
750 | 'path': '/dev/sdX1', | |
751 | 'whoami': '5566', | |
752 | 'mount': '/var/lib/ceph/osd/ceph-5566/', | |
753 | 'uuid': part_uuid, | |
754 | }]}] | |
755 | with patch.multiple( | |
756 | main, | |
757 | list_devices=lambda: fake_device, | |
758 | _check_osd_status=lambda cluster, osd_id: 2, | |
759 | _mark_osd_out=lambda cluster, osd_id: True | |
760 | ): | |
761 | main.main_deactivate(args) | |
762 | ||
763 | # | |
764 | # find match device by device partition, status: OSD_STATUS_IN_DOWN | |
765 | # | |
766 | args = main.parse_args(['deactivate', | |
767 | '--cluster', 'ceph', | |
768 | '/dev/sdX1']) | |
769 | fake_device = [{'path': '/dev/' + disk, | |
770 | 'partitions': [{ | |
771 | 'ptype': DMCRYPT_LUKS_OSD_UUID, | |
772 | 'path': '/dev/sdX1', | |
773 | 'whoami': '5566', | |
774 | 'mount': '/var/lib/ceph/osd/ceph-5566/', | |
775 | 'uuid': part_uuid, | |
776 | }]}] | |
777 | with patch.multiple( | |
778 | main, | |
779 | list_devices=lambda: fake_device, | |
780 | _check_osd_status=lambda cluster, osd_id: 0, | |
781 | ): | |
782 | main.main_deactivate(args) | |
783 | ||
784 | # | |
785 | # find match device by device partition, status: OSD_STATUS_IN_UP | |
786 | # with --mark-out option | |
787 | # | |
788 | args = main.parse_args(['deactivate', | |
789 | '--cluster', 'ceph', | |
790 | '/dev/sdX1', | |
791 | '--mark-out']) | |
792 | fake_device = [{'path': '/dev/' + disk, | |
793 | 'partitions': [{ | |
794 | 'ptype': DMCRYPT_LUKS_OSD_UUID, | |
795 | 'path': '/dev/sdX1', | |
796 | 'whoami': '5566', | |
797 | 'mount': '/var/lib/ceph/osd/ceph-5566/', | |
798 | 'uuid': part_uuid, | |
799 | }]}] | |
800 | ||
801 | # mock the file open. | |
802 | file_opened = io.StringIO() | |
803 | file_opened.write(u'deactive') | |
804 | mock_open.return_value = file_opened | |
805 | ||
806 | with patch.multiple( | |
807 | main, | |
808 | mock_open, | |
809 | list_devices=lambda: fake_device, | |
810 | _check_osd_status=lambda cluster, osd_id: 3, | |
811 | _mark_osd_out=lambda cluster, osd_id: True, | |
812 | stop_daemon=lambda cluster, osd_id: True, | |
813 | _remove_osd_directory_files=lambda path, cluster: True, | |
814 | path_set_context=lambda path: True, | |
d2e6a577 | 815 | unmount=lambda path, do_rm: True, |
7c673cae FG |
816 | dmcrypt_unmap=lambda part_uuid: True, |
817 | ): | |
818 | main.main_deactivate(args) | |
819 | ||
820 | # | |
821 | # find match device by osd-id, status: OSD_STATUS_OUT_UP | |
822 | # | |
823 | args = main.parse_args(['deactivate', | |
824 | '--cluster', 'ceph', | |
825 | '--deactivate-by-id', '5566']) | |
826 | fake_device = [{'path': '/dev/' + disk, | |
827 | 'partitions': [{ | |
828 | 'ptype': DMCRYPT_LUKS_OSD_UUID, | |
829 | 'path': '/dev/sdX1', | |
830 | 'whoami': '5566', | |
831 | 'mount': '/var/lib/ceph/osd/ceph-5566/', | |
832 | 'uuid': part_uuid, | |
833 | }]}] | |
834 | ||
835 | # mock the file open. | |
836 | file_opened = io.StringIO() | |
837 | file_opened.write(u'deactive') | |
838 | mock_open.return_value = file_opened | |
839 | ||
840 | with patch.multiple( | |
841 | main, | |
842 | mock_open, | |
843 | list_devices=lambda: fake_device, | |
844 | _check_osd_status=lambda cluster, osd_id: 1, | |
845 | _mark_osd_out=lambda cluster, osd_id: True, | |
846 | stop_daemon=lambda cluster, osd_id: True, | |
847 | _remove_osd_directory_files=lambda path, cluster: True, | |
848 | path_set_context=lambda path: True, | |
d2e6a577 | 849 | unmount=lambda path, do_rm: True, |
7c673cae FG |
850 | dmcrypt_unmap=lambda part_uuid: True, |
851 | ): | |
852 | main.main_deactivate(args) | |
853 | shutil.rmtree(data) | |
854 | ||
855 | def test_mark_out_out(self): | |
856 | def mark_osd_out_fail(osd_id): | |
857 | raise main.Error('Could not find osd.%s, is a vaild/exist osd id?' | |
858 | % osd_id) | |
859 | ||
860 | with patch.multiple( | |
861 | main, | |
862 | command=mark_osd_out_fail, | |
863 | ): | |
864 | self.assertRaises(Exception, main._mark_osd_out, 'ceph', '5566') | |
865 | ||
866 | def test_check_osd_status(self): | |
867 | # | |
868 | # command failure | |
869 | # | |
870 | with patch.multiple( | |
871 | main, | |
872 | command=raise_command_error, | |
873 | ): | |
874 | self.assertRaises(Exception, main._check_osd_status, | |
875 | 'ceph', '5566') | |
876 | ||
877 | # | |
878 | # osd not found | |
879 | # | |
880 | ||
881 | fake_data = ('{"osds":[{"osd":0,"up":1,"in":1},' | |
882 | '{"osd":1,"up":1,"in":1}]}') | |
883 | ||
884 | def return_fake_value(cmd): | |
885 | return fake_data, '', 0 | |
886 | ||
887 | with patch.multiple( | |
888 | main, | |
889 | command=return_fake_value, | |
890 | ): | |
891 | self.assertRaises(Exception, main._check_osd_status, | |
892 | 'ceph', '5566') | |
893 | ||
894 | # | |
895 | # successfully | |
896 | # | |
897 | ||
898 | fake_data = ('{"osds":[{"osd":0,"up":1,"in":1},' | |
899 | '{"osd":5566,"up":1,"in":1}]}') | |
900 | ||
901 | def return_fake_value(cmd): | |
902 | return fake_data, '', 0 | |
903 | ||
904 | with patch.multiple( | |
905 | main, | |
906 | command=return_fake_value, | |
907 | ): | |
908 | main._check_osd_status('ceph', '5566') | |
909 | ||
910 | def test_stop_daemon(self): | |
911 | STATEDIR = '/var/lib/ceph' | |
912 | cluster = 'ceph' | |
913 | osd_id = '5566' | |
914 | ||
915 | def stop_daemon_fail(cmd): | |
916 | raise Exception('ceph osd stop failed') | |
917 | ||
918 | # | |
919 | # fail on init type | |
920 | # | |
921 | with patch('os.path.exists', return_value=False): | |
922 | self.assertRaises(Exception, main.stop_daemon, 'ceph', '5566') | |
923 | ||
924 | # | |
925 | # upstart failure | |
926 | # | |
927 | fake_path = (STATEDIR + '/osd/{cluster}-{osd_id}/upstart').format( | |
928 | cluster=cluster, osd_id=osd_id) | |
929 | ||
930 | def path_exist(check_path): | |
931 | if check_path == fake_path: | |
932 | return True | |
933 | else: | |
934 | False | |
935 | ||
936 | patcher = patch('os.path.exists') | |
937 | check_path = patcher.start() | |
938 | check_path.side_effect = path_exist | |
939 | with patch.multiple( | |
940 | main, | |
941 | check_path, | |
942 | command_check_call=stop_daemon_fail, | |
943 | ): | |
944 | self.assertRaises(Exception, main.stop_daemon, 'ceph', '5566') | |
945 | ||
946 | # | |
947 | # sysvinit failure | |
948 | # | |
949 | fake_path = (STATEDIR + '/osd/{cluster}-{osd_id}/sysvinit').format( | |
950 | cluster=cluster, osd_id=osd_id) | |
951 | ||
952 | def path_exist(check_path): | |
953 | if check_path == fake_path: | |
954 | return True | |
955 | else: | |
956 | return False | |
957 | ||
958 | patcher = patch('os.path.exists') | |
959 | check_path = patcher.start() | |
960 | check_path.side_effect = path_exist | |
961 | with patch.multiple( | |
962 | main, | |
963 | check_path, | |
964 | which=lambda name: True, | |
965 | command_check_call=stop_daemon_fail, | |
966 | ): | |
967 | self.assertRaises(Exception, main.stop_daemon, 'ceph', '5566') | |
968 | ||
969 | # | |
970 | # systemd failure | |
971 | # | |
972 | fake_path = (STATEDIR + '/osd/{cluster}-{osd_id}/systemd').format( | |
973 | cluster=cluster, osd_id=osd_id) | |
974 | ||
975 | def path_exist(check_path): | |
976 | if check_path == fake_path: | |
977 | return True | |
978 | else: | |
979 | False | |
980 | ||
981 | def stop_daemon_fail(cmd): | |
982 | if 'stop' in cmd: | |
983 | raise Exception('ceph osd stop failed') | |
984 | else: | |
985 | return True | |
986 | ||
987 | patcher = patch('os.path.exists') | |
988 | check_path = patcher.start() | |
989 | check_path.side_effect = path_exist | |
990 | with patch.multiple( | |
991 | main, | |
992 | check_path, | |
993 | command_check_call=stop_daemon_fail, | |
994 | ): | |
995 | self.assertRaises(Exception, main.stop_daemon, 'ceph', '5566') | |
996 | ||
997 | def test_remove_osd_directory_files(self): | |
998 | cluster = 'ceph' | |
999 | mounted_path = 'somewhere' | |
1000 | fake_path_2 = None | |
1001 | fake_path_remove_2 = None | |
1002 | fake_path_remove_init = None | |
1003 | ||
1004 | def handle_path_exist(check_path): | |
1005 | if check_path == fake_path: | |
1006 | return True | |
1007 | elif fake_path_2 and check_path == fake_path_2: | |
1008 | return True | |
1009 | else: | |
1010 | return False | |
1011 | ||
1012 | def handle_path_remove(remove_path): | |
1013 | if remove_path == fake_path_remove: | |
1014 | return True | |
1015 | elif fake_path_remove_2 and remove_path == fake_path_remove_2: | |
1016 | return True | |
1017 | elif (fake_path_remove_init and | |
1018 | remove_path == fake_path_remove_init): | |
1019 | return True | |
1020 | else: | |
1021 | raise OSError | |
1022 | ||
1023 | # | |
1024 | # remove ready file failure | |
1025 | # | |
1026 | fake_path = os.path.join(mounted_path, 'ready') | |
1027 | fake_path_remove = os.path.join(mounted_path, 'no_ready') | |
1028 | ||
1029 | patcher_exist = patch('os.path.exists') | |
1030 | patcher_remove = patch('os.remove') | |
1031 | path_exist = patcher_exist.start() | |
1032 | path_remove = patcher_remove.start() | |
1033 | path_exist.side_effect = handle_path_exist | |
1034 | path_remove.side_effect = handle_path_remove | |
1035 | with patch.multiple( | |
1036 | main, | |
1037 | path_exist, | |
1038 | path_remove, | |
1039 | get_conf=lambda cluster, **kwargs: True, | |
1040 | ): | |
1041 | self.assertRaises(Exception, main._remove_osd_directory_files, | |
1042 | 'somewhere', cluster) | |
1043 | ||
1044 | # | |
1045 | # remove active fil failure | |
1046 | # | |
1047 | fake_path = os.path.join(mounted_path, 'ready') | |
1048 | fake_path_2 = os.path.join(mounted_path, 'active') | |
1049 | fake_path_remove = os.path.join(mounted_path, 'ready') | |
1050 | fake_path_remove_2 = os.path.join(mounted_path, 'no_active') | |
1051 | ||
1052 | patcher_exist = patch('os.path.exists') | |
1053 | patcher_remove = patch('os.remove') | |
1054 | path_exist = patcher_exist.start() | |
1055 | path_remove = patcher_remove.start() | |
1056 | path_exist.side_effect = handle_path_exist | |
1057 | path_remove.side_effect = handle_path_remove | |
1058 | with patch.multiple( | |
1059 | main, | |
1060 | path_exist, | |
1061 | path_remove, | |
1062 | get_conf=lambda cluster, **kwargs: True, | |
1063 | ): | |
1064 | self.assertRaises(Exception, main._remove_osd_directory_files, | |
1065 | 'somewhere', cluster) | |
1066 | ||
1067 | # | |
1068 | # conf_val is None and remove init file failure | |
1069 | # | |
1070 | fake_path = os.path.join(mounted_path, 'ready') | |
1071 | fake_path_2 = os.path.join(mounted_path, 'active') | |
1072 | fake_path_remove = os.path.join(mounted_path, 'ready') | |
1073 | fake_path_remove_2 = os.path.join(mounted_path, 'active') | |
1074 | fake_path_remove_init = os.path.join(mounted_path, 'init_failure') | |
1075 | ||
1076 | patcher_exist = patch('os.path.exists') | |
1077 | patcher_remove = patch('os.remove') | |
1078 | path_exist = patcher_exist.start() | |
1079 | path_remove = patcher_remove.start() | |
1080 | path_exist.side_effect = handle_path_exist | |
1081 | path_remove.side_effect = handle_path_remove | |
1082 | with patch.multiple( | |
1083 | main, | |
1084 | path_exist, | |
1085 | path_remove, | |
1086 | get_conf=lambda cluster, **kwargs: None, | |
1087 | init_get=lambda: 'upstart', | |
1088 | ): | |
1089 | self.assertRaises(Exception, main._remove_osd_directory_files, | |
1090 | 'somewhere', cluster) | |
1091 | ||
1092 | # | |
1093 | # already remove `ready`, `active` and remove init file successfully | |
1094 | # | |
1095 | fake_path = os.path.join(mounted_path, 'no_ready') | |
1096 | fake_path_2 = os.path.join(mounted_path, 'no_active') | |
1097 | fake_path_remove = os.path.join(mounted_path, 'upstart') | |
1098 | ||
1099 | patcher_exist = patch('os.path.exists') | |
1100 | patcher_remove = patch('os.remove') | |
1101 | path_exist = patcher_exist.start() | |
1102 | path_remove = patcher_remove.start() | |
1103 | path_exist.side_effect = handle_path_exist | |
1104 | path_remove.side_effect = handle_path_remove | |
1105 | with patch.multiple( | |
1106 | main, | |
1107 | path_exist, | |
1108 | path_remove, | |
1109 | get_conf=lambda cluster, **kwargs: 'upstart', | |
1110 | ): | |
1111 | main._remove_osd_directory_files('somewhere', cluster) | |
1112 | ||
1113 | def test_path_set_context(self): | |
1114 | path = '/somewhere' | |
1115 | with patch.multiple( | |
1116 | main, | |
1117 | get_ceph_user=lambda **kwargs: 'ceph', | |
1118 | ): | |
1119 | main.path_set_context(path) | |
1120 | ||
1121 | def test_mount(self): | |
1122 | # | |
1123 | # None to mount | |
1124 | # | |
1125 | dev = None | |
1126 | fs_type = 'ext4' | |
1127 | option = '' | |
1128 | self.assertRaises(Exception, main.mount, dev, fs_type, option) | |
1129 | ||
1130 | # | |
1131 | # fstype undefine | |
1132 | # | |
1133 | dev = '/dev/Xda1' | |
1134 | fs_type = None | |
1135 | option = '' | |
1136 | self.assertRaises(Exception, main.mount, dev, fs_type, option) | |
1137 | ||
1138 | # | |
1139 | # mount failure | |
1140 | # | |
1141 | dev = '/dev/Xda1' | |
1142 | fstype = 'ext4' | |
1143 | options = '' | |
1144 | with patch('tempfile.mkdtemp', return_value='/mnt'): | |
1145 | self.assertRaises(Exception, main.mount, dev, fstype, options) | |
1146 | ||
1147 | # | |
1148 | # mount successfully | |
1149 | # | |
1150 | def create_temp_directory(*args, **kwargs): | |
1151 | return '/mnt' | |
1152 | ||
1153 | dev = '/dev/Xda1' | |
1154 | fstype = 'ext4' | |
1155 | options = '' | |
1156 | patcher = patch('tempfile.mkdtemp') | |
1157 | create_tmpdir = patcher.start() | |
1158 | create_tmpdir.side_effect = create_temp_directory | |
1159 | with patch.multiple( | |
1160 | main, | |
1161 | create_tmpdir, | |
1162 | command_check_call=lambda cmd: True, | |
1163 | ): | |
1164 | main.mount(dev, fstype, options) | |
1165 | ||
1166 | def test_umount(self): | |
1167 | # | |
1168 | # umount failure | |
1169 | # | |
1170 | path = '/somewhere' | |
1171 | self.assertRaises(Exception, main.unmount, path) | |
1172 | ||
1173 | # | |
1174 | # umount successfully | |
1175 | # | |
1176 | def remove_directory_successfully(path): | |
1177 | return True | |
1178 | ||
1179 | path = '/somewhere' | |
1180 | patcher = patch('os.rmdir') | |
1181 | rm_directory = patcher.start() | |
1182 | rm_directory.side_effect = remove_directory_successfully | |
1183 | with patch.multiple( | |
1184 | main, | |
1185 | rm_directory, | |
1186 | command_check_call=lambda cmd: True, | |
1187 | ): | |
1188 | main.unmount(path) | |
1189 | ||
1190 | def test_main_destroy(self): | |
1191 | data = tempfile.mkdtemp() | |
1192 | main.setup_statedir(data) | |
1193 | OSD_UUID = '4fbd7e29-9d25-41b8-afd0-062c0ceff05d' | |
1194 | MPATH_OSD_UUID = '4fbd7e29-8ae0-4982-bf9d-5a8d867af560' | |
1195 | part_uuid = '0ce28a16-6d5d-11e5-aec3-fa163e5c167b' | |
1196 | journal_uuid = "7ad5e65a-0ca5-40e4-a896-62a74ca61c55" | |
1197 | mount_5566 = '/var/lib/ceph/osd/ceph-5566/' | |
1198 | ||
1199 | fake_devices_normal = [{'path': '/dev/sdY', | |
1200 | 'partitions': [{ | |
1201 | 'dmcrypt': {}, | |
1202 | 'type': 'osd', | |
1203 | 'ptype': OSD_UUID, | |
1204 | 'path': '/dev/sdY1', | |
1205 | 'whoami': '5566', | |
1206 | 'mount': mount_5566, | |
1207 | 'uuid': part_uuid, | |
1208 | 'journal_uuid': journal_uuid}]}, | |
1209 | {'path': '/dev/sdX', | |
1210 | 'partitions': [{ | |
1211 | 'dmcrypt': {}, | |
1212 | 'type': 'osd', | |
1213 | 'ptype': MPATH_OSD_UUID, | |
1214 | 'path': '/dev/sdX1', | |
1215 | 'whoami': '7788', | |
1216 | 'mount': '/var/lib/ceph/osd/ceph-7788/', | |
1217 | 'uuid': part_uuid, | |
1218 | 'journal_uuid': journal_uuid}]}] | |
1219 | ||
1220 | def list_devices_return(): | |
1221 | return fake_devices_normal | |
1222 | ||
1223 | # | |
1224 | # input device is not the device partition | |
1225 | # | |
1226 | args = main.parse_args(['destroy', '--cluster', 'ceph', '/dev/sdX']) | |
1227 | with patch.multiple( | |
1228 | main, | |
1229 | is_partition=lambda path: False, | |
1230 | ): | |
1231 | self.assertRaises(Exception, main.main_destroy, args) | |
1232 | ||
1233 | # | |
1234 | # skip the redundent devices and not found by dev | |
1235 | # | |
1236 | args = main.parse_args(['destroy', '--cluster', 'ceph', '/dev/sdZ1']) | |
1237 | with patch.multiple( | |
1238 | main, | |
1239 | is_partition=lambda path: True, | |
1240 | list_devices=list_devices_return, | |
1241 | ): | |
1242 | self.assertRaises(Exception, main.main_destroy, args) | |
1243 | ||
1244 | # | |
1245 | # skip the redundent devices and not found by osd-id | |
1246 | # | |
1247 | args = main.parse_args(['destroy', '--cluster', 'ceph', | |
1248 | '--destroy-by-id', '1234']) | |
1249 | with patch.multiple( | |
1250 | main, | |
1251 | is_partition=lambda path: True, | |
1252 | list_devices=list_devices_return, | |
1253 | ): | |
1254 | self.assertRaises(Exception, main.main_destroy, args) | |
1255 | ||
1256 | # | |
1257 | # skip the redundent devices and found by dev | |
1258 | # | |
1259 | args = main.parse_args(['destroy', '--cluster', | |
1260 | 'ceph', '/dev/sdY1', '--zap']) | |
1261 | with patch.multiple( | |
1262 | main, | |
1263 | is_partition=lambda path: True, | |
1264 | list_devices=list_devices_return, | |
1265 | get_partition_base=lambda dev_path: '/dev/sdY', | |
1266 | _check_osd_status=lambda cluster, osd_id: 0, | |
7c673cae FG |
1267 | zap=lambda dev: True |
1268 | ): | |
1269 | main.main_destroy(args) | |
1270 | ||
1271 | # | |
1272 | # skip the redundent devices and found by osd-id | |
1273 | # with active status and MPATH_OSD | |
1274 | # | |
1275 | args = main.parse_args(['destroy', '--cluster', 'ceph', | |
1276 | '--destroy-by-id', '7788']) | |
1277 | with patch.multiple( | |
1278 | main, | |
1279 | is_partition=lambda path: True, | |
1280 | list_devices=list_devices_return, | |
1281 | get_partition_base_mpath=lambda dev_path: '/dev/sdX', | |
1282 | _check_osd_status=lambda cluster, osd_id: 1, | |
1283 | ): | |
1284 | self.assertRaises(Exception, main.main_destroy, args) | |
1285 | shutil.rmtree(data) | |
1286 | ||
7c673cae FG |
1287 | def test_main_fix(self): |
1288 | if platform.system() == "FreeBSD": | |
1289 | return | |
1290 | ||
1291 | args = main.parse_args(['fix', '--all', '--selinux', '--permissions']) | |
1292 | commands = [] | |
1293 | ||
1294 | def _command(x): | |
1295 | commands.append(" ".join(x)) | |
1296 | return ("", "", None) | |
1297 | ||
31f18b77 FG |
1298 | class Os(object): |
1299 | F_OK = 0 | |
1300 | ||
1301 | @staticmethod | |
1302 | def access(x, y): | |
1303 | return True | |
1304 | ||
7c673cae FG |
1305 | with patch.multiple( |
1306 | main, | |
1307 | command=_command, | |
1308 | command_init=lambda x: commands.append(x), | |
1309 | command_wait=lambda x: None, | |
31f18b77 | 1310 | os=Os, |
7c673cae FG |
1311 | ): |
1312 | main.main_fix(args) | |
1313 | commands = " ".join(commands) | |
1314 | assert '/var/lib/ceph' in commands | |
1315 | assert 'restorecon' in commands | |
1316 | assert 'chown' in commands | |
1317 | assert 'find' in commands | |
1318 | ||
1319 | ||
1320 | def raise_command_error(*args): | |
1321 | e = subprocess.CalledProcessError('aaa', 'bbb', 'ccc') | |
1322 | raise e |