Skip to content

Commit 1107f5b

Browse files
committed
ceph-volume: add type annotations to devices.lvm.batch
This commit adds the Python type annotations to `devices.lvm.batch`. Signed-off-by: Guillaume Abrioux <[email protected]>
1 parent 12b1e7e commit 1107f5b

File tree

2 files changed

+113
-117
lines changed

2 files changed

+113
-117
lines changed

src/ceph-volume/ceph_volume/api/lvm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ def __init__(self, **kw: Any) -> None:
836836
self.lv_name: str = ''
837837
self.lv_uuid: str = ''
838838
self.vg_name: str = ''
839+
self.lv_size: str = ''
839840
self.lv_tags: Dict[str, Any] = {}
840841
for k, v in kw.items():
841842
setattr(self, k, v)

src/ceph-volume/ceph_volume/devices/lvm/batch.py

Lines changed: 112 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
import logging
55
from textwrap import dedent
66
from 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
88
from ceph_volume.util import prepare
99
from . import common
1010
from .create import Create
1111
from .prepare import Prepare
12+
from typing import Any, Dict, List, Optional, Tuple
1213

1314
mlogger = terminal.MultiLogger(__name__)
1415
logger = logging.getLogger(__name__)
@@ -18,87 +19,29 @@
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

Comments
 (0)