]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph-volume: pick strategy for batch with only the unused devices
authorAndrew Schoen <aschoen@redhat.com>
Thu, 27 Sep 2018 20:22:17 +0000 (15:22 -0500)
committerAndrew Schoen <aschoen@redhat.com>
Mon, 15 Oct 2018 16:55:50 +0000 (11:55 -0500)
This will pick a strategy, filter out any devices already been used by
ceph and then pick a strategy again. If the strategy has changed the
call should error, if the strategy is the same proceed. If there are no
unused devices then the command is a noop.

Signed-off-by: Andrew Schoen <aschoen@redhat.com>
(cherry picked from commit 4529f2d6053b0b07583a3d7501f4e05e08cad385)

src/ceph-volume/ceph_volume/devices/lvm/batch.py
src/ceph-volume/ceph_volume/devices/lvm/strategies/filestore.py
src/ceph-volume/ceph_volume/util/device.py

index 45e99c5a795b466a5fd61ead2abad8df671aaf4f..a643e0aa186773729f648e77473cfa15b9c457c7 100644 (file)
@@ -5,6 +5,8 @@ from ceph_volume.util import disk, prompt_bool
 from ceph_volume.util import arg_validators
 from . import strategies
 
+mlogger = terminal.MultiLogger(__name__)
+
 
 device_list_template = """
   * {path: <25} {size: <10} {state}"""
@@ -62,7 +64,7 @@ def filestore_mixed_type(device_facts):
         return strategies.filestore.MixedType
 
 
-def get_strategy(args):
+def get_strategy(args, devices):
     """
     Given a set of devices as input, go through the different detection
     mechanisms to narrow down on a strategy to use. The strategies are 4 in
@@ -85,9 +87,9 @@ def get_strategy(args):
         strategies = filestore_strategies
 
     for strategy in strategies:
-        backend = strategy(args.devices)
+        backend = strategy(devices)
         if backend:
-            return backend(args.devices, args)
+            return backend
 
 
 class Batch(object):
@@ -128,7 +130,7 @@ class Batch(object):
         )
 
     def report(self, args):
-        strategy = get_strategy(args)
+        strategy = self._get_strategy(args)
         if args.format == 'pretty':
             strategy.report_pretty()
         elif args.format == 'json':
@@ -137,7 +139,7 @@ class Batch(object):
             raise RuntimeError('report format must be "pretty" or "json"')
 
     def execute(self, args):
-        strategy = get_strategy(args)
+        strategy = self._get_strategy(args)
         if not args.yes:
             strategy.report_pretty()
             terminal.info('The above OSDs would be created if the operation continues')
@@ -148,6 +150,31 @@ class Batch(object):
 
         strategy.execute()
 
+    def _get_strategy(self, args):
+        strategy = get_strategy(args, args.devices)
+        unused_devices = [device for device in args.devices if not device.used_by_ceph]
+        # only data devices, journals can be reused
+        used_devices = [device.abspath for device in args.devices if device.used_by_ceph]
+        args.filtered_devices = {}
+        if used_devices:
+            for device in used_devices:
+                args.filtered_devices[device] = {"reasons": ["Used by ceph as a data device already"]}
+            if not args.report:
+                mlogger.info("Ignoring devices already used by ceph: %s" % ",".join(used_devices))
+        if not unused_devices and not args.report:
+            # report nothing changed
+            mlogger.info("All devices are already used by ceph. No OSDs will be created.")
+            raise SystemExit(0)
+        else:
+            new_strategy = get_strategy(args, unused_devices)
+            if type(strategy) != type(new_strategy):
+                if not args.report:
+                    mlogger.error("aborting because strategy changed from %s to %s after filtering" % (strategy, new_strategy))
+                    raise SystemExit(0)
+            else:
+                strategy = new_strategy
+        return strategy(unused_devices, args)
+
     @decorators.needs_root
     def main(self):
         parser = argparse.ArgumentParser(
index fa7dc6ecb883f7fe3db88b23b862689d21e5c7bb..d2a3bd54fe71aed2b0ae085c1a76b0603bb2bf18 100644 (file)
@@ -31,7 +31,7 @@ class SingleType(object):
         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.computed = {'osds': [], 'vgs': []}
+        self.computed = {'osds': [], 'vgs': [], 'filtered_devices': args.filtered_devices}
         self.journal_size = get_journal_size(args)
         self.validate()
         self.compute()
@@ -99,7 +99,6 @@ class SingleType(object):
         # chose whichever is the one group we have to compute against
         devices = self.hdds or self.ssds
         osds = self.computed['osds']
-        used_osds = []
         for device in devices:
             for osd in range(self.osds_per_device):
                 device_size = disk.Size(b=device.sys_api['size'])
@@ -107,7 +106,6 @@ class SingleType(object):
                 journal_size = self.journal_size
                 data_size = osd_size - journal_size
                 data_percentage = data_size * 100 / device_size
-                used_osds.append(device.used_by_ceph)
                 osd = {'data': {}, 'journal': {}, 'used_by_ceph': device.used_by_ceph}
                 osd['data']['path'] = device.abspath
                 osd['data']['size'] = data_size.b.as_int()
@@ -120,7 +118,7 @@ class SingleType(object):
                 osd['journal']['human_readable_size'] = str(journal_size)
                 osds.append(osd)
 
-        self.computed['changed'] = not any(used_osds)
+        self.computed['changed'] = len(osds) > 0
 
     def execute(self):
         """
index 2eb68d18f18358fa7de9a5b66f8a33610cc560d7..6e355fc4a648feee73c65ea85a214ed6cdf71e1e 100644 (file)
@@ -118,7 +118,9 @@ class Device(object):
 
     @property
     def used_by_ceph(self):
-        osd_ids = [lv.tags.get("ceph.osd_id") for lv in self.lvs]
+        # only filter out data devices as journals could potentially be reused
+        osd_ids = [lv.tags.get("ceph.osd_id") for lv in self.lvs
+                   if lv.tags.get("ceph.type") == "data"]
         return any(osd_ids)