From 60dec8b1dfdd056662ba6a030de291f93b2f3650 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Tue, 27 Nov 2018 15:49:01 +0100 Subject: [PATCH] ceph-volume: refactor strategies for explicit device arguments This commit refactors lvm strategies to: a) change the constructor to receive usage specific device lists b) add classmethod with_auto_devices of automatic splitting by the rotational flag (keep backwards compatible behavior) c) rename ssds and hdds member variables to wal_devs and block_devs d) add db_devs member variable Signed-off-by: Jan Fajerski --- .../ceph_volume/devices/lvm/batch.py | 8 ++-- .../devices/lvm/strategies/bluestore.py | 42 +++++++++++------- .../devices/lvm/strategies/filestore.py | 44 ++++++++++++------- .../devices/lvm/strategies/strategies.py | 23 ++++++---- 4 files changed, 74 insertions(+), 43 deletions(-) diff --git a/src/ceph-volume/ceph_volume/devices/lvm/batch.py b/src/ceph-volume/ceph_volume/devices/lvm/batch.py index 6fec784e5d0..4d14181c37e 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/batch.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/batch.py @@ -300,13 +300,15 @@ class Batch(object): if not self.args.bluestore and not self.args.filestore: self.args.bluestore = True - if not self.args.no_auto: + if (self.args.no_auto or self.args.db_devices or + self.args.journal_devices or + self.args.wal_devices): + self.get_explicit_strategy() + else: if self.args.report: self.report() else: self.execute() - else: - self.get_explicit_strategy() def get_explicit_strategy(self): raise NotImplementedError() diff --git a/src/ceph-volume/ceph_volume/devices/lvm/strategies/bluestore.py b/src/ceph-volume/ceph_volume/devices/lvm/strategies/bluestore.py index d0630e768a7..f9d8b809514 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/strategies/bluestore.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/strategies/bluestore.py @@ -15,10 +15,15 @@ class SingleType(Strategy): Support for all SSDs, or all HDDS """ - def __init__(self, devices, args): - super(SingleType, self).__init__(devices, args) + def __init__(self, block_devs, db_devs, wal_devs, args): + super(SingleType, self).__init__(block_devs, db_devs, wal_devs, args) self.validate_compute() + @classmethod + def with_auto_devices(cls, devices, args): + block_devs, wal_devs = cls.split_devices_rotational(devices) + return cls(block_devs, wal_devs, [], args) + @staticmethod def type(): return "bluestore.SingleType" @@ -54,7 +59,7 @@ class SingleType(Strategy): ) # make sure that data devices do not have any LVs - validators.no_lvm_membership(self.hdds) + validators.no_lvm_membership(self.block_devs) def compute(self): """ @@ -62,7 +67,7 @@ class SingleType(Strategy): a dictionary with the result """ osds = self.computed['osds'] - for device in self.hdds: + for device in self.block_devs: for hdd in range(self.osds_per_device): osd = {'data': {}, 'block.db': {}} osd['data']['path'] = device.abspath @@ -74,7 +79,7 @@ class SingleType(Strategy): ) osds.append(osd) - for device in self.ssds: + for device in self.wal_devs: extents = lvm.sizing(device.lvm_size.b, parts=self.osds_per_device) for ssd in range(self.osds_per_device): osd = {'data': {}, 'block.db': {}} @@ -124,14 +129,19 @@ class SingleType(Strategy): class MixedType(MixedStrategy): - def __init__(self, devices, args): - super(MixedType, self).__init__(devices, args) + def __init__(self, block_devs, db_devs, wal_devs, args): + super(MixedType, self).__init__(block_devs, db_devs, wal_devs, args) self.block_db_size = self.get_block_size() self.system_vgs = lvm.VolumeGroups() - self.dbs_needed = len(self.hdds) * self.osds_per_device + self.dbs_needed = len(self.block_devs) * self.osds_per_device self.use_large_block_db = False self.validate_compute() + @classmethod + def with_auto_devices(cls, devices, args): + block_devs, db_devs = cls.split_devices_rotational(devices) + return cls(block_devs, db_devs, [], args) + @staticmethod def type(): return "bluestore.MixedType" @@ -150,7 +160,7 @@ class MixedType(MixedStrategy): if self.args.filtered_devices: string += templates.filtered_devices(self.args.filtered_devices) string += templates.total_osds.format( - total_osds=len(self.hdds) * self.osds_per_device + total_osds=len(self.block_devs) * self.osds_per_device ) string += templates.ssd_volume_group.format( @@ -158,9 +168,9 @@ class MixedType(MixedStrategy): total_lv_size=str(self.total_available_db_space), total_lvs=vg_extents['parts'] * self.osds_per_device, block_lv_size=db_size, - block_db_devices=', '.join([ssd.abspath for ssd in self.ssds]), + block_db_devices=', '.join([ssd.abspath for ssd in self.db_devs]), lv_size=self.block_db_size or str(disk.Size(b=(vg_extents['sizes']))), - total_osds=len(self.hdds) + total_osds=len(self.block_devs) ) string += templates.osd_component_titles @@ -199,7 +209,7 @@ class MixedType(MixedStrategy): else: vg_name = self.common_vg.name - for device in self.hdds: + for device in self.block_devs: for hdd in range(self.osds_per_device): osd = {'data': {}, 'block.db': {}} osd['data']['path'] = device.abspath @@ -294,10 +304,10 @@ class MixedType(MixedStrategy): validators.minimum_device_size(self.devices, osds_per_device=self.osds_per_device) # make sure that data devices do not have any LVs - validators.no_lvm_membership(self.hdds) + validators.no_lvm_membership(self.block_devs) # do not allow non-common VG to continue - validators.has_common_vg(self.ssds) + validators.has_common_vg(self.db_devs) # find the common VG to calculate how much is available self.common_vg = self.get_common_vg() @@ -309,8 +319,8 @@ class MixedType(MixedStrategy): common_vg_size = disk.Size(gb=0) # non-VG SSDs - self.vg_ssds = set([d for d in self.ssds if d.is_lvm_member]) - self.blank_ssds = set(self.ssds).difference(self.vg_ssds) + self.vg_ssds = set([d for d in self.db_devs if d.is_lvm_member]) + self.blank_ssds = set(self.db_devs).difference(self.vg_ssds) self.total_blank_ssd_size = disk.Size(b=0) for blank_ssd in self.blank_ssds: self.total_blank_ssd_size += disk.Size(b=blank_ssd.lvm_size.b) diff --git a/src/ceph-volume/ceph_volume/devices/lvm/strategies/filestore.py b/src/ceph-volume/ceph_volume/devices/lvm/strategies/filestore.py index a642893d4be..5cede7e10bb 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/strategies/filestore.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/strategies/filestore.py @@ -27,11 +27,17 @@ class SingleType(Strategy): in the same device """ - def __init__(self, devices, args): - super(SingleType, self).__init__(devices, args) + + def __init__(self, block_devs, db_devs, args): + super(SingleType, self).__init__(block_devs, db_devs, [], args) self.journal_size = get_journal_size(args) self.validate_compute() + @classmethod + def with_auto_devices(cls, devices, args): + block_devs, wal_devs = cls.split_devices_rotational(devices) + return cls(block_devs, wal_devs, args) + @staticmethod def type(): return "filestore.SingleType" @@ -71,17 +77,17 @@ class SingleType(Strategy): validators.minimum_device_size(self.devices, osds_per_device=self.osds_per_device) # validate collocation - if self.hdds: + if self.block_devs: validators.minimum_device_collocated_size( - self.hdds, self.journal_size, osds_per_device=self.osds_per_device + self.block_devs, self.journal_size, osds_per_device=self.osds_per_device ) else: validators.minimum_device_collocated_size( - self.ssds, self.journal_size, osds_per_device=self.osds_per_device + self.wal_devs, self.journal_size, osds_per_device=self.osds_per_device ) # make sure that data devices do not have any LVs - validators.no_lvm_membership(self.hdds) + validators.no_lvm_membership(self.block_devs) def compute(self): """ @@ -89,7 +95,7 @@ class SingleType(Strategy): a dictionary with the result """ # chose whichever is the one group we have to compute against - devices = self.hdds or self.ssds + devices = self.block_devs or self.wal_devs osds = self.computed['osds'] for device in devices: for osd in range(self.osds_per_device): @@ -167,14 +173,20 @@ class MixedType(MixedStrategy): SSDs are used, otherwise it will be used directly. """ - def __init__(self, devices, args): - super(MixedType, self).__init__(devices, args) + + def __init__(self, block_devs, db_devs, args): + super(MixedType, self).__init__(block_devs, db_devs, [], args) self.blank_ssds = [] - self.journals_needed = len(self.hdds) * self.osds_per_device + self.journals_needed = len(self.block_devs) * self.osds_per_device self.journal_size = get_journal_size(args) self.system_vgs = lvm.VolumeGroups() self.validate_compute() + @classmethod + def with_auto_devices(cls, devices, args): + block_devs, db_devs = cls.split_devices_rotational(devices) + return cls(block_devs, db_devs, args) + @staticmethod def type(): return "filestore.MixedType" @@ -191,7 +203,7 @@ class MixedType(MixedStrategy): target='journal', total_lv_size=str(self.total_available_journal_space), total_lvs=self.journals_needed, - block_db_devices=', '.join([d.path for d in self.ssds]), + block_db_devices=', '.join([d.path for d in self.db_devs]), lv_size=str(self.journal_size), total_osds=self.journals_needed ) @@ -224,10 +236,10 @@ class MixedType(MixedStrategy): validators.minimum_device_size(self.devices, osds_per_device=self.osds_per_device) # make sure that data devices do not have any LVs - validators.no_lvm_membership(self.hdds) + validators.no_lvm_membership(self.block_devs) # do not allow non-common VG to continue - validators.has_common_vg(self.ssds) + validators.has_common_vg(self.db_devs) # find the common VG to calculate how much is available self.common_vg = self.get_common_vg() @@ -239,8 +251,8 @@ class MixedType(MixedStrategy): common_vg_size = disk.Size(gb=0) # non-VG SSDs - self.vg_ssds = set([d for d in self.ssds if d.is_lvm_member]) - self.blank_ssds = set(self.ssds).difference(self.vg_ssds) + self.vg_ssds = set([d for d in self.db_devs if d.is_lvm_member]) + self.blank_ssds = set(self.db_devs).difference(self.vg_ssds) self.total_blank_ssd_size = disk.Size(b=0) for blank_ssd in self.blank_ssds: self.total_blank_ssd_size += disk.Size(b=blank_ssd.lvm_size.b) @@ -290,7 +302,7 @@ class MixedType(MixedStrategy): else: vg_name = self.common_vg.name - for device in self.hdds: + for device in self.block_devs: for osd in range(self.osds_per_device): device_size = disk.Size(b=device.lvm_size.b) data_size = device_size / self.osds_per_device diff --git a/src/ceph-volume/ceph_volume/devices/lvm/strategies/strategies.py b/src/ceph-volume/ceph_volume/devices/lvm/strategies/strategies.py index d4ec5a73091..4c5dd9d4999 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/strategies/strategies.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/strategies/strategies.py @@ -2,14 +2,21 @@ import json class Strategy(object): - def __init__(self, devices, args): + def __init__(self, block_devs, db_devs, wal_devs, args): self.args = args self.osds_per_device = args.osds_per_device - self.devices = devices - self.hdds = [device for device in devices if device.sys_api['rotational'] == '1'] - self.ssds = [device for device in devices if device.sys_api['rotational'] == '0'] + self.devices = block_devs + wal_devs + db_devs + self.block_devs = block_devs + self.db_devs = db_devs self.computed = {'osds': [], 'vgs': [], 'filtered_devices': args.filtered_devices} + @staticmethod + def split_devices_rotational(devices): + block_devs = [device for device in devices if device.sys_api['rotational'] == '1'] + db_devs = [device for device in devices if device.sys_api['rotational'] == '0'] + return block_devs, db_devs + + def validate_compute(self): if self.devices: self.validate() @@ -22,10 +29,10 @@ class Strategy(object): @property def total_osds(self): - if self.hdds: - return len(self.hdds) * self.osds_per_device + if self.block_devs: + return len(self.block_devs) * self.osds_per_device else: - return len(self.ssds) * self.osds_per_device + return len(self.wal_devs) * self.osds_per_device # protect against base class instantiation and incomplete implementations. # We could also use the abc module and implement this as an @@ -40,7 +47,7 @@ class MixedStrategy(Strategy): def get_common_vg(self): # find all the vgs associated with the current device - for ssd in self.ssds: + for ssd in self.db_devs: for pv in ssd.pvs_api: vg = self.system_vgs.get(vg_name=pv.vg_name) if not vg: -- 2.39.5