44import logging
55from textwrap import dedent
66from ceph_volume import terminal , decorators
7- from ceph_volume .util import disk , prompt_bool , arg_validators , templates
7+ from ceph_volume .util import device , disk , prompt_bool , arg_validators , templates
88from ceph_volume .util import prepare
99from . import common
1010from .create import Create
1111from .prepare import Prepare
12+ from typing import Any , Dict , List , Optional , Tuple
1213
1314mlogger = terminal .MultiLogger (__name__ )
1415logger = logging .getLogger (__name__ )
1819 * {path: <25} {size: <10} {state}"""
1920
2021
21- def device_formatter (devices ):
22- lines = []
23- for path , details in devices :
24- lines .append (device_list_template .format (
25- path = path , size = details ['human_readable_size' ],
26- state = 'solid' if details ['rotational' ] == '0' else 'rotational' )
27- )
28-
29- return '' .join (lines )
30-
31-
32- def ensure_disjoint_device_lists (data , db = [], wal = []):
22+ def ensure_disjoint_device_lists (data : List [str ],
23+ db : Optional [List [str ]] = None ,
24+ wal : Optional [List [str ]] = None ) -> None :
25+ if db is None :
26+ db = []
27+ if wal is None :
28+ wal = []
3329 # check that all device lists are disjoint with each other
3430 if not all ([set (data ).isdisjoint (set (db )),
3531 set (data ).isdisjoint (set (wal )),
3632 set (db ).isdisjoint (set (wal ))]):
3733 raise Exception ('Device lists are not disjoint' )
3834
3935
40- def separate_devices_from_lvs (devices ) :
36+ def separate_devices_from_lvs (devices : List [ device . Device ]) -> Tuple [ List [ device . Device ], List [ device . Device ]] :
4137 phys = []
4238 lvm = []
4339 for d in devices :
4440 phys .append (d ) if d .is_device else lvm .append (d )
4541 return phys , lvm
4642
4743
48- def get_physical_osds (devices , args ):
49- '''
50- Goes through passed physical devices and assigns OSDs
51- '''
52- data_slots = args .osds_per_device
53- if args .data_slots :
54- data_slots = max (args .data_slots , args .osds_per_device )
55- rel_data_size = args .data_allocate_fraction / data_slots
56- mlogger .debug ('relative data size: {}' .format (rel_data_size ))
57- ret = []
58- for dev in devices :
59- if dev .available_lvm :
60- dev_size = dev .vg_size [0 ]
61- abs_size = disk .Size (b = int (dev_size * rel_data_size ))
62- free_size = dev .vg_free [0 ]
63- for _ in range (args .osds_per_device ):
64- if abs_size > free_size :
65- break
66- free_size -= abs_size .b
67- osd_id = None
68- if args .osd_ids :
69- osd_id = args .osd_ids .pop ()
70- ret .append (Batch .OSD (dev .path ,
71- rel_data_size ,
72- abs_size ,
73- args .osds_per_device ,
74- osd_id ,
75- 'dmcrypt' if args .dmcrypt else None ,
76- dev .symlink ))
77- return ret
78-
79-
80- def get_lvm_osds (lvs , args ):
81- '''
82- Goes through passed LVs and assigns planned osds
83- '''
84- ret = []
85- for lv in lvs :
86- if lv .used_by_ceph :
87- continue
88- osd_id = None
89- if args .osd_ids :
90- osd_id = args .osd_ids .pop ()
91- osd = Batch .OSD ("{}/{}" .format (lv .vg_name , lv .lv_name ),
92- 100.0 ,
93- disk .Size (b = int (lv .lvs [0 ].lv_size )),
94- 1 ,
95- osd_id ,
96- 'dmcrypt' if args .dmcrypt else None )
97- ret .append (osd )
98- return ret
99-
100-
101- def get_physical_fast_allocs (devices , type_ , fast_slots_per_device , new_osds , args ):
44+ def get_physical_fast_allocs (devices : List [device .Device ], type_ : str , fast_slots_per_device : int , new_osds : int , args : argparse .Namespace ) -> List [Tuple [str , float , disk .Size , int ]]:
10245 requested_slots = getattr (args , '{}_slots' .format (type_ ))
10346 if not requested_slots or requested_slots < fast_slots_per_device :
10447 if requested_slots :
@@ -111,7 +54,7 @@ def get_physical_fast_allocs(devices, type_, fast_slots_per_device, new_osds, ar
11154 get_size_fct = getattr (prepare , 'get_{}_size' .format (type_ ))
11255 requested_size = get_size_fct (lv_format = False )
11356
114- ret = []
57+ ret : List [ Tuple [ str , float , disk . Size , int ]] = []
11558 vg_device_map = group_devices_by_vg (devices )
11659 for vg_name , vg_devices in vg_device_map .items ():
11760 for dev in vg_devices :
@@ -153,8 +96,8 @@ def get_physical_fast_allocs(devices, type_, fast_slots_per_device, new_osds, ar
15396 ret .append ((dev .path , relative_size , abs_size , requested_slots ))
15497 return ret
15598
156- def group_devices_by_vg (devices ) :
157- result = dict ()
99+ def group_devices_by_vg (devices : List [ device . Device ]) -> Dict [ str , Any ] :
100+ result : Dict [ str , Any ] = dict ()
158101 result ['unused_devices' ] = []
159102 for dev in devices :
160103 if len (dev .vgs ) > 0 :
@@ -167,7 +110,7 @@ def group_devices_by_vg(devices):
167110 result ['unused_devices' ].append (dev )
168111 return result
169112
170- def get_lvm_fast_allocs (lvs ) :
113+ def get_lvm_fast_allocs (lvs : List [ device . Device ]) -> List [ Tuple [ str , float , disk . Size , int ]] :
171114 return [("{}/{}" .format (d .vg_name , d .lv_name ), 100.0 ,
172115 disk .Size (b = int (d .lvs [0 ].lv_size )), 1 ) for d in lvs if not
173116 d .journal_used_by_ceph ]
@@ -190,7 +133,7 @@ class Batch(object):
190133 ceph-volume lvm batch --report [DEVICE...]
191134 """ )
192135
193- def __init__ (self , argv ) :
136+ def __init__ (self , argv : List [ str ]) -> None :
194137 parser = argparse .ArgumentParser (
195138 prog = 'ceph-volume lvm batch' ,
196139 formatter_class = argparse .RawDescriptionHelpFormatter ,
@@ -342,39 +285,39 @@ def __init__(self, argv):
342285 for dev_list in ['' , 'db_' , 'wal_' ]:
343286 setattr (self , '{}usable' .format (dev_list ), [])
344287
345- def report (self , plan ) :
288+ def report (self , plan : List [ "OSD" ]) -> None :
346289 report = self ._create_report (plan )
347290 print (report )
348291
349- def _create_report (self , plan ):
292+ def _create_report (self , plan : List ["OSD" ]) -> str :
293+ result : str = ''
350294 if self .args .format == 'pretty' :
351- report = ''
352- report += templates .total_osds .format (total_osds = len (plan ))
295+ result += templates .total_osds .format (total_osds = len (plan ))
353296
354- report += templates .osd_component_titles
297+ result += templates .osd_component_titles
355298 for osd in plan :
356- report += templates .osd_header
357- report += osd .report ()
358- return report
299+ result += templates .osd_header
300+ result += osd .report ()
359301 else :
360302 json_report = []
361303 for osd in plan :
362304 json_report .append (osd .report_json ())
363305 if self .args .format == 'json' :
364- return json .dumps (json_report )
306+ result = json .dumps (json_report )
365307 elif self .args .format == 'json-pretty' :
366- return json .dumps (json_report , indent = 4 ,
308+ result = json .dumps (json_report , indent = 4 ,
367309 sort_keys = True )
310+ return result
368311
369- def _check_slot_args (self ):
312+ def _check_slot_args (self ) -> None :
370313 '''
371314 checking if -slots args are consistent with other arguments
372315 '''
373316 if self .args .data_slots and self .args .osds_per_device :
374317 if self .args .data_slots < self .args .osds_per_device :
375318 raise ValueError ('data_slots is smaller then osds_per_device' )
376319
377- def _sort_rotational_disks (self ):
320+ def _sort_rotational_disks (self ) -> None :
378321 '''
379322 Helper for legacy auto behaviour.
380323 Sorts drives into rotating and non-rotating, the latter being used for
@@ -393,9 +336,10 @@ def _sort_rotational_disks(self):
393336 self .args .db_devices = ssd
394337
395338 @decorators .needs_root
396- def main (self ):
339+ def main (self ) -> None :
397340 if not self .args .devices :
398- return self .parser .print_help ()
341+ self .parser .print_help ()
342+ raise SystemExit (0 )
399343
400344 if (self .args .auto and not self .args .db_devices and not
401345 self .args .wal_devices ):
@@ -411,7 +355,7 @@ def main(self):
411355
412356 if self .args .report :
413357 self .report (plan )
414- return 0
358+ return
415359
416360 if not self .args .yes :
417361 self .report (plan )
@@ -422,7 +366,7 @@ def main(self):
422366
423367 self ._execute (plan )
424368
425- def _execute (self , plan ) :
369+ def _execute (self , plan : List [ "OSD" ]) -> None :
426370 defaults = common .get_default_args ()
427371 global_args = [
428372 'bluestore' ,
@@ -441,7 +385,7 @@ def _execute(self, plan):
441385 c = Create ([], args = argparse .Namespace (** args ))
442386 c .create ()
443387
444- def get_deployment_layout (self ):
388+ def get_deployment_layout (self ) -> List [ "OSD" ] :
445389 '''
446390 The methods here are mostly just organization, error reporting and
447391 setting up of (default) args. The heavy lifting code for the deployment
@@ -500,8 +444,8 @@ def get_deployment_layout(self):
500444 osd .add_very_fast_device (* very_fast_allocations .pop ())
501445 return plan
502446
503- def fast_allocations (self , devices , requested_osds , new_osds , type_ ) :
504- ret = []
447+ def fast_allocations (self , devices : List [ device . Device ] , requested_osds : int , new_osds : int , type_ : str ) -> List [ Tuple [ str , float , disk . Size , int ]] :
448+ ret : List [ Tuple [ str , float , disk . Size , int ]] = []
505449 if not devices :
506450 return ret
507451 phys_devs , lvm_devs = separate_devices_from_lvs (devices )
@@ -540,39 +484,39 @@ class OSD(object):
540484 'type_' ])
541485
542486 def __init__ (self ,
543- data_path ,
544- rel_size ,
545- abs_size ,
546- slots ,
547- id_ ,
548- encryption ,
549- symlink = None ):
487+ data_path : str ,
488+ rel_size : float ,
489+ abs_size : disk . Size ,
490+ slots : int ,
491+ id_ : Optional [ str ] = None ,
492+ encryption : Optional [ str ] = None ,
493+ symlink : Optional [ str ] = None ) -> None :
550494 self .id_ = id_
551495 self .data = self .VolSpec (path = data_path ,
552496 rel_size = rel_size ,
553497 abs_size = abs_size ,
554498 slots = slots ,
555499 type_ = 'data' )
556- self .fast = None
557- self .very_fast = None
558- self .encryption = encryption
559- self .symlink = symlink
500+ self .fast : Optional [ Any ] = None
501+ self .very_fast : Optional [ Any ] = None
502+ self .encryption : Optional [ str ] = encryption
503+ self .symlink : Optional [ str ] = symlink
560504
561- def add_fast_device (self , path , rel_size , abs_size , slots , type_ ) :
505+ def add_fast_device (self , path : str , rel_size : float , abs_size : disk . Size , slots : int , type_ : str ) -> None :
562506 self .fast = self .VolSpec (path = path ,
563- rel_size = rel_size ,
564- abs_size = abs_size ,
565- slots = slots ,
566- type_ = type_ )
507+ rel_size = rel_size ,
508+ abs_size = abs_size ,
509+ slots = slots ,
510+ type_ = type_ )
567511
568- def add_very_fast_device (self , path , rel_size , abs_size , slots ) :
512+ def add_very_fast_device (self , path : str , rel_size : float , abs_size : disk . Size , slots : int ) -> None :
569513 self .very_fast = self .VolSpec (path = path ,
570- rel_size = rel_size ,
571- abs_size = abs_size ,
572- slots = slots ,
573- type_ = 'block_wal' )
514+ rel_size = rel_size ,
515+ abs_size = abs_size ,
516+ slots = slots ,
517+ type_ = 'block_wal' )
574518
575- def _get_osd_plan (self ):
519+ def _get_osd_plan (self ) -> Dict [ str , Any ] :
576520 plan = {
577521 'data' : self .data .path ,
578522 'data_size' : self .data .abs_size ,
@@ -595,12 +539,12 @@ def _get_osd_plan(self):
595539 plan .update ({'osd_id' : self .id_ })
596540 return plan
597541
598- def get_args (self , defaults ) :
542+ def get_args (self , defaults : Dict [ str , Any ]) -> Dict [ str , Any ] :
599543 my_defaults = defaults .copy ()
600544 my_defaults .update (self ._get_osd_plan ())
601545 return my_defaults
602546
603- def report (self ):
547+ def report (self ) -> str :
604548 report = ''
605549 if self .id_ :
606550 report += templates .osd_reused_id .format (
@@ -630,7 +574,58 @@ def report(self):
630574 percent = self .very_fast .rel_size )
631575 return report
632576
633- def report_json (self ):
577+ def report_json (self ) -> Dict [ str , Any ] :
634578 # cast all values to string so that the report can be dumped in to
635579 # json.dumps
636580 return {k : str (v ) for k , v in self ._get_osd_plan ().items ()}
581+
582+ def get_physical_osds (devices : List [device .Device ], args : argparse .Namespace ) -> List [Batch .OSD ]:
583+ '''
584+ Goes through passed physical devices and assigns OSDs
585+ '''
586+ data_slots = args .osds_per_device
587+ if args .data_slots :
588+ data_slots = max (args .data_slots , args .osds_per_device )
589+ rel_data_size = args .data_allocate_fraction / data_slots
590+ mlogger .debug ('relative data size: {}' .format (rel_data_size ))
591+ ret = []
592+ for dev in devices :
593+ if dev .available_lvm :
594+ dev_size = dev .vg_size [0 ]
595+ abs_size = disk .Size (b = int (dev_size * rel_data_size ))
596+ free_size = dev .vg_free [0 ]
597+ for _ in range (args .osds_per_device ):
598+ if abs_size > free_size :
599+ break
600+ free_size -= abs_size .b
601+ osd_id = None
602+ if args .osd_ids :
603+ osd_id = args .osd_ids .pop ()
604+ ret .append (Batch .OSD (dev .path ,
605+ rel_data_size ,
606+ abs_size ,
607+ args .osds_per_device ,
608+ osd_id ,
609+ 'dmcrypt' if args .dmcrypt else None ,
610+ dev .symlink ))
611+ return ret
612+
613+ def get_lvm_osds (lvs : List [device .Device ], args : argparse .Namespace ) -> List [Batch .OSD ]:
614+ '''
615+ Goes through passed LVs and assigns planned osds
616+ '''
617+ ret = []
618+ for lv in lvs :
619+ if lv .used_by_ceph :
620+ continue
621+ osd_id = None
622+ if args .osd_ids :
623+ osd_id = args .osd_ids .pop ()
624+ osd = Batch .OSD ("{}/{}" .format (lv .vg_name , lv .lv_name ),
625+ 100.0 ,
626+ disk .Size (b = int (lv .lvs [0 ].lv_size )),
627+ 1 ,
628+ osd_id ,
629+ 'dmcrypt' if args .dmcrypt else None )
630+ ret .append (osd )
631+ return ret
0 commit comments