]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
ceph-volume: add drive-group subcommand
authorJan Fajerski <jfajerski@suse.com>
Tue, 21 Apr 2020 13:47:42 +0000 (15:47 +0200)
committerJan Fajerski <jfajerski@suse.com>
Thu, 23 Jul 2020 10:10:58 +0000 (12:10 +0200)
This new subcommand takes a drive group specification as json and deploys
the OSDs accordingly.

Signed-off-by: Jan Fajerski <jfajerski@suse.com>
Fixes: https://tracker.ceph.com/issues/46689
doc/ceph-volume/drive-group.rst [new file with mode: 0644]
doc/ceph-volume/index.rst
src/ceph-volume/ceph_volume/drive_group/__init__.py [new file with mode: 0644]
src/ceph-volume/ceph_volume/drive_group/main.py [new file with mode: 0644]
src/ceph-volume/ceph_volume/inventory/main.py
src/ceph-volume/ceph_volume/main.py
src/ceph-volume/setup.py
src/python-common/.gitignore
src/python-common/ceph/deployment/drive_group.py
src/python-common/ceph/deployment/translate.py

diff --git a/doc/ceph-volume/drive-group.rst b/doc/ceph-volume/drive-group.rst
new file mode 100644 (file)
index 0000000..4b2b8ed
--- /dev/null
@@ -0,0 +1,12 @@
+.. _ceph-volume-drive-group:
+
+``drive-group``
+===============
+The drive-group subcommand allows for passing :ref:'drivegroups' specifications
+straight to ceph-volume as json. ceph-volume will then attempt to deploy this
+drive groups via the batch subcommand.
+
+The specification can be passed via a file, string argument or on stdin.
+See the subcommand help for further details::
+
+    # ceph-volume drive-group --help
index 36ce9cc8910ee7f279a19cf46f7ca9005c6bfb29..a9c18abb7228c7f9bc9029626e378601f74bbab0 100644 (file)
@@ -65,6 +65,7 @@ and ``ceph-disk`` is fully disabled. Encryption is fully supported.
    intro
    systemd
    inventory
+   drive-group
    lvm/index
    lvm/activate
    lvm/batch
diff --git a/src/ceph-volume/ceph_volume/drive_group/__init__.py b/src/ceph-volume/ceph_volume/drive_group/__init__.py
new file mode 100644 (file)
index 0000000..14a0fd7
--- /dev/null
@@ -0,0 +1 @@
+from .main import Deploy # noqa
diff --git a/src/ceph-volume/ceph_volume/drive_group/main.py b/src/ceph-volume/ceph_volume/drive_group/main.py
new file mode 100644 (file)
index 0000000..684e89f
--- /dev/null
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+
+import argparse
+import json
+import logging
+import sys
+
+from ceph.deployment.drive_group import DriveGroupSpec
+from ceph.deployment.drive_selection.selector import DriveSelection
+from ceph.deployment.translate import to_ceph_volume
+from ceph.deployment.inventory import Device
+from ceph_volume.inventory import Inventory
+from ceph_volume.devices.lvm.batch import Batch
+
+logger = logging.getLogger(__name__)
+
+class Deploy(object):
+
+    help = '''
+    Deploy OSDs according to a drive groups specification.
+
+    The DriveGroup specification must be passed in json.
+    It can either be (preference in this order)
+      - in a file, path passed as a positional argument
+      - read from stdin, pass "-" as a positional argument
+      - a json string passed via the --spec argument
+
+    Either the path postional argument or --spec must be specifed.
+    '''
+
+    def __init__(self, argv):
+        logger.error(f'argv: {argv}')
+        self.argv = argv
+
+    def main(self):
+        parser = argparse.ArgumentParser(
+            prog='ceph-volume drive-group',
+            formatter_class=argparse.RawDescriptionHelpFormatter,
+            description=self.help,
+        )
+        parser.add_argument(
+            'path',
+            nargs='?',
+            default=None,
+            help=('Path to file containing drive group spec or "-" to read from stdin'),
+        )
+        parser.add_argument(
+            '--spec',
+            default='',
+            nargs='?',
+            help=('drive-group json string')
+        )
+        parser.add_argument(
+            '--dry-run',
+            default=False,
+            action='store_true',
+            help=('dry run, only print the batch command that would be run'),
+        )
+        self.args = parser.parse_args(self.argv)
+        if self.args.path:
+            if self.args.path == "-":
+                commands = self.from_json(sys.stdin)
+            else:
+                with open(self.args.path, 'r') as f:
+                    commands = self.from_json(f)
+        elif self.args.spec:
+            dg = json.loads(self.args.spec)
+            commands = self.get_dg_spec(dg)
+        else:
+            # either --spec or path arg must be specified
+            parser.print_help(sys.stderr)
+            sys.exit(0)
+        cmd = commands.run()
+        if not cmd:
+            logger.error('DriveGroup didn\'t produce any commands')
+            return
+        if self.args.dry_run:
+            logger.info('Returning ceph-volume command (--dry-run was passed): {}'.format(cmd))
+            print(cmd)
+        else:
+            logger.info('Running ceph-volume command: {}'.format(cmd))
+            batch_args = cmd.split(' ')[2:]
+            b = Batch(batch_args)
+            b.main()
+
+    def from_json(self, file_):
+        dg = {}
+        dg = json.load(file_)
+        return self.get_dg_spec(dg)
+
+    def get_dg_spec(self, dg):
+        dg_spec = DriveGroupSpec._from_json_impl(dg)
+        dg_spec.validate()
+        i = Inventory([])
+        i.main()
+        inventory = i.get_report()
+        devices = [Device.from_json(i) for i in inventory]
+        selection = DriveSelection(dg_spec, devices)
+        return to_ceph_volume(selection)
index 1d821b602be18329330a800174e90ab1738074f7..470be274f52ebb2d30048ecfaecaa78230ca97df 100644 (file)
@@ -37,6 +37,12 @@ class Inventory(object):
         else:
             self.format_report(Devices())
 
+    def get_report(self):
+        if self.args.path:
+            return Device(self.args.path).json_report()
+        else:
+            return Devices().json_report()
+
     def format_report(self, inventory):
         if self.args.format == 'json':
             print(json.dumps(inventory.json_report()))
index 8c5801c5db59e394d8795d6a70421bc692b14f50..461395ae5e3342d88afaafe1826cbce4734f0767 100644 (file)
@@ -6,7 +6,7 @@ import sys
 import logging
 
 from ceph_volume.decorators import catches
-from ceph_volume import log, devices, configuration, conf, exceptions, terminal, inventory
+from ceph_volume import log, devices, configuration, conf, exceptions, terminal, inventory, drive_group
 
 
 class Volume(object):
@@ -29,6 +29,7 @@ Ceph Conf: {ceph_path}
             'simple': devices.simple.Simple,
             'raw': devices.raw.Raw,
             'inventory': inventory.Inventory,
+            'drive-group': drive_group.Deploy,
         }
         self.plugin_help = "No plugins found/loaded"
         if argv is None:
index 9bd48178cbf4fd51a43bcb8b3c4f9bb87189d937..a9fbdf8985b1d1d14baf5e9273faf2b5b9348883 100644 (file)
@@ -1,4 +1,5 @@
 from setuptools import setup, find_packages
+import os
 
 
 setup(
@@ -13,6 +14,9 @@ setup(
     keywords='ceph volume disk devices lvm',
     url="https://github.com/ceph/ceph",
     zip_safe = False,
+    install_requires='ceph',
+    dependency_links=[''.join(['file://', os.path.join(os.getcwd(), '../',
+                                                       'python-common#egg=ceph-1.0.0')])],
     tests_require=[
         'pytest >=2.1.3',
         'tox',
index 3e38dc9bf7d0d98997b1dea543865999936fca36..c2de8195a1cfdf6a43981a3dba2ff585aa00bb30 100644 (file)
@@ -1,2 +1,3 @@
 ceph.egg-info
 build
+setup.cfg
index a4307f6e73ac1532f95588716e283f034e9b6338..eed8fc2ef2b1e4317f70e0cbc44b63266806fdfe 100644 (file)
@@ -191,7 +191,7 @@ class DriveGroupSpec(ServiceSpec):
         #: Set (or override) the "bluestore_block_db_size" value, in bytes
         self.block_db_size = block_db_size
 
-        #: set journal_size is bytes
+        #: set journal_size in bytes
         self.journal_size = journal_size
 
         #: Number of osd daemons per "DATA" device.
index 7eb0ec1d5059ce470d75f054f900c381e0bd113b..c2f030d2cb26fa00885d5126dd207d273b835f3d 100644 (file)
@@ -10,6 +10,7 @@ from ceph.deployment.drive_selection.selector import DriveSelection
 logger = logging.getLogger(__name__)
 
 
+# TODO refactor this to a DriveSelection method
 class to_ceph_volume(object):
 
     def __init__(self,