]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph-volume: lvm.prepare: initial pass at a working prepare
authorAlfredo Deza <adeza@redhat.com>
Tue, 11 Jul 2017 20:36:16 +0000 (16:36 -0400)
committerAlfredo Deza <adeza@redhat.com>
Fri, 4 Aug 2017 14:25:57 +0000 (10:25 -0400)
Signed-off-by: Alfredo Deza <adeza@redhat.com>
src/ceph-volume/ceph_volume/devices/lvm/prepare.py

index 03307783bdd207bceec23cf0a7d135a75e567381..ef63e5ea1900a8979d7104a559e4d87acf082139 100644 (file)
@@ -1,8 +1,47 @@
 import argparse
+import os
 from textwrap import dedent
-from ceph_volume import process
-from ceph_volume.systemd import systemctl
-import api
+from ceph_volume.util import prepare as prepare_utils
+from ceph_volume.util import system
+from ceph_volume import conf
+from . import api
+
+
+def canonical_device_path(device):
+    """
+    Ensure that a device is canonical (full path) and that it exists so that
+    it can be used throughout the prepare/activate process
+    """
+    # FIXME: this is obviously super naive
+    inferred = os.path.join('/dev', device)
+    if os.path.exists(os.path.abspath(device)):
+        return device
+    elif os.path.exists(inferred):
+        return inferred
+    raise RuntimeError('Selected device does not exist: %s' % device)
+
+
+def prepare_filestore(device, journal, id_=None, fsid=None):
+    # allow re-using an existing fsid, in case prepare failed
+    fsid = fsid or system.generate_uuid()
+    # allow re-using an id, in case a prepare failed
+    osd_id = id_ or prepare_utils.create_id(fsid)
+    # create the directory
+    prepare_utils.create_path(osd_id)
+    # format the device
+    prepare_utils.format_device(device)
+    # mount the data device
+    prepare_utils.mount_osd(device, osd_id)
+    # symlink the journal
+    prepare_utils.link_journal(journal, osd_id)
+    # get the latest monmap
+    prepare_utils.get_monmap(osd_id)
+    # prepare the osd filesystem
+    prepare_utils.osd_mkfs(osd_id, fsid)
+
+
+def prepare_bluestore():
+    raise NotImplemented()
 
 
 class Prepare(object):
@@ -12,6 +51,87 @@ class Prepare(object):
     def __init__(self, argv):
         self.argv = argv
 
+    def prepare(self, args):
+        cluster_fsid = conf.ceph.get('global', 'fsid')
+        fsid = args.osd_fsid or system.generate_uuid()
+        osd_id = args.osd_id or prepare_utils.create_id(fsid)
+        journal_name = "journal_%s" % fsid
+        osd_name = "osd_%s" % fsid
+        if args.filestore:
+            data_vg = api.get_vg(vg_name=args.data)
+            data_lv = api.get_lv(lv_name=args.data)
+            journal_vg = api.get_vg(vg_name=args.journal)
+            journal_lv = api.get_lv(lv_name=args.journal)
+            journal_device = None
+            # it is possible to pass a device as a journal that is not
+            # an actual logical volume (or group)
+            if not args.journal:
+                if data_lv:
+                    raise RuntimeError('--journal is required when not using a vg for OSD data')
+                # collocated: carve out the journal from the data vg
+                if data_vg:
+                    journal_lv = api.create_lv(
+                        name=journal_name,
+                        group=data_vg.name,
+                        size=args.journal_size,
+                        osd_fsid=fsid,
+                        osd_id=osd_id,
+                        type='journal',
+                        cluster_fsid=cluster_fsid
+                    )
+
+            # if a volume group was defined for the journal create that first
+            if journal_vg:
+                journal_lv = api.create_lv(
+                    name=journal_name,
+                    group=args.journal,
+                    size=args.journal_size,
+                    osd_fsid=fsid,
+                    osd_id=osd_id,
+                    type='journal',
+                    cluster_fsid=cluster_fsid
+                )
+            if journal_lv:
+                journal_device = journal_lv.lv_path
+            # The journal is probably a device, not in LVM
+            elif args.journal:
+                journal_device = canonical_device_path(args.journal)
+            # At this point we must have a journal_lv or a journal device
+            # now create the osd from the group if that was found
+            if data_vg:
+                # XXX make sure that a there aren't more OSDs than physical
+                # devices from this volume group
+                data_lv = api.create_lv(
+                    name=osd_name,
+                    group=args.data,
+                    osd_fsid=fsid,
+                    osd_id=osd_id,
+                    type='data',
+                    journal_device=journal_device,
+                    cluster_fsid=cluster_fsid
+                )
+            # we must have either an existing data_lv or a newly created, so lets make
+            # sure that the tags are correct
+            data_lv.set_tags({
+                'ceph.type': 'data',
+                'ceph.osd_fsid': fsid,
+                'ceph.osd_id': osd_id,
+                'ceph.cluster_fsid': cluster_fsid,
+                'ceph.journal_device': journal_device,
+                'ceph.data_device': data_lv.lv_path,
+            })
+            if not data_lv:
+                raise RuntimeError('no data logical volume found with: %s' % args.data)
+
+            prepare_filestore(
+                data_lv.lv_path,
+                journal_device,
+                id_=osd_id,
+                fsid=fsid,
+            )
+        elif args.bluestore:
+            prepare_bluestore(args)
+
     def main(self):
         sub_command_help = dedent("""
         Prepare an OSD by assigning an ID and FSID, registering them with the
@@ -34,7 +154,7 @@ class Prepare(object):
 
           Existing logical volume (lv) or device:
 
-              ceph-volume lvm prepare --data {volume group} --journal /path/to/{lv}|{device}
+              ceph-volume lvm prepare --data {logical volume} --journal /path/to/{lv}|{device}
 
           Or:
 
@@ -78,5 +198,13 @@ class Prepare(object):
             action='store_true', default=True,
             help='Use the filestore objectstore (currently the only supported object store)',
         )
+        parser.add_argument(
+            '--osd-id',
+            help='Reuse an existing OSD id',
+        )
+        parser.add_argument(
+            '--osd-fsid',
+            help='Reuse an existing OSD fsid',
+        )
         args = parser.parse_args(self.argv[1:])
-        self.activate(args)
+        self.prepare(args)