initial code repo
[stor4nfv.git] / src / ceph / src / ceph-volume / ceph_volume / util / prepare.py
diff --git a/src/ceph/src/ceph-volume/ceph_volume/util/prepare.py b/src/ceph/src/ceph-volume/ceph_volume/util/prepare.py
new file mode 100644 (file)
index 0000000..026ccaf
--- /dev/null
@@ -0,0 +1,257 @@
+"""
+These utilities for prepare provide all the pieces needed to prepare a device
+but also a compounded ("single call") helper to do them in order. Some plugins
+may want to change some part of the process, while others might want to consume
+the single-call helper
+"""
+import os
+import logging
+from ceph_volume import process, conf
+from ceph_volume.util import system, constants
+
+logger = logging.getLogger(__name__)
+
+
+def create_key():
+    stdout, stderr, returncode = process.call(['ceph-authtool', '--gen-print-key'])
+    if returncode != 0:
+        raise RuntimeError('Unable to generate a new auth key')
+    return ' '.join(stdout).strip()
+
+
+def write_keyring(osd_id, secret):
+    # FIXME this only works for cephx, but there will be other types of secrets
+    # later
+    osd_keyring = '/var/lib/ceph/osd/%s-%s/keyring' % (conf.cluster, osd_id)
+    process.run(
+        [
+            'ceph-authtool', osd_keyring,
+            '--create-keyring',
+            '--name', 'osd.%s' % str(osd_id),
+            '--add-key', secret
+        ])
+    system.chown(osd_keyring)
+    # TODO: do the restorecon dance on the osd_keyring path
+
+
+def create_id(fsid, json_secrets):
+    """
+    :param fsid: The osd fsid to create, always required
+    :param json_secrets: a json-ready object with whatever secrets are wanted
+                         to be passed to the monitor
+    """
+    bootstrap_keyring = '/var/lib/ceph/bootstrap-osd/%s.keyring' % conf.cluster
+    stdout, stderr, returncode = process.call(
+        [
+            'ceph',
+            '--cluster', conf.cluster,
+            '--name', 'client.bootstrap-osd',
+            '--keyring', bootstrap_keyring,
+            '-i', '-',
+            'osd', 'new', fsid
+        ],
+        stdin=json_secrets
+    )
+    if returncode != 0:
+        raise RuntimeError('Unable to create a new OSD id')
+    return ' '.join(stdout).strip()
+
+
+def mount_tmpfs(path):
+    process.run([
+        'mount',
+        '-t',
+        'tmpfs', 'tmpfs',
+        path
+    ])
+
+
+def create_osd_path(osd_id, tmpfs=False):
+    path = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
+    system.mkdir_p('/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id))
+    if tmpfs:
+        mount_tmpfs(path)
+
+
+def format_device(device):
+    # only supports xfs
+    command = ['mkfs', '-t', 'xfs']
+
+    # get the mkfs options if any for xfs,
+    # fallback to the default options defined in constants.mkfs
+    flags = conf.ceph.get_list(
+        'osd',
+        'osd_mkfs_options_xfs',
+        default=constants.mkfs.get('xfs'),
+        split=' ',
+    )
+
+    # always force
+    if '-f' not in flags:
+        flags.insert(0, '-f')
+
+    command.extend(flags)
+    command.append(device)
+    process.run(command)
+
+
+def mount_osd(device, osd_id):
+    destination = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
+    command = ['mount', '-t', 'xfs', '-o']
+    flags = conf.ceph.get_list(
+        'osd',
+        'osd_mount_options_xfs',
+        default=constants.mount.get('xfs'),
+        split=' ',
+    )
+    command.append(flags)
+    command.append(device)
+    command.append(destination)
+    process.run(command)
+
+
+def _link_device(device, device_type, osd_id):
+    """
+    Allow linking any device type in an OSD directory. ``device`` must the be
+    source, with an absolute path and ``device_type`` will be the destination
+    name, like 'journal', or 'block'
+    """
+    device_path = '/var/lib/ceph/osd/%s-%s/%s' % (
+        conf.cluster,
+        osd_id,
+        device_type
+    )
+    command = ['ln', '-s', device, device_path]
+    system.chown(device)
+
+    process.run(command)
+
+
+def link_journal(journal_device, osd_id):
+    _link_device(journal_device, 'journal', osd_id)
+
+
+def link_block(block_device, osd_id):
+    _link_device(block_device, 'block', osd_id)
+
+
+def link_wal(wal_device, osd_id):
+    _link_device(wal_device, 'block.wal', osd_id)
+
+
+def link_db(db_device, osd_id):
+    _link_device(db_device, 'block.db', osd_id)
+
+
+def get_monmap(osd_id):
+    """
+    Before creating the OSD files, a monmap needs to be retrieved so that it
+    can be used to tell the monitor(s) about the new OSD. A call will look like::
+
+        ceph --cluster ceph --name client.bootstrap-osd \
+             --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring \
+             mon getmap -o /var/lib/ceph/osd/ceph-0/activate.monmap
+    """
+    path = '/var/lib/ceph/osd/%s-%s/' % (conf.cluster, osd_id)
+    bootstrap_keyring = '/var/lib/ceph/bootstrap-osd/%s.keyring' % conf.cluster
+    monmap_destination = os.path.join(path, 'activate.monmap')
+
+    process.run([
+        'ceph',
+        '--cluster', conf.cluster,
+        '--name', 'client.bootstrap-osd',
+        '--keyring', bootstrap_keyring,
+        'mon', 'getmap', '-o', monmap_destination
+    ])
+
+
+def osd_mkfs_bluestore(osd_id, fsid, keyring=None, wal=False, db=False):
+    """
+    Create the files for the OSD to function. A normal call will look like:
+
+          ceph-osd --cluster ceph --mkfs --mkkey -i 0 \
+                   --monmap /var/lib/ceph/osd/ceph-0/activate.monmap \
+                   --osd-data /var/lib/ceph/osd/ceph-0 \
+                   --osd-uuid 8d208665-89ae-4733-8888-5d3bfbeeec6c \
+                   --keyring /var/lib/ceph/osd/ceph-0/keyring \
+                   --setuser ceph --setgroup ceph
+
+    In some cases it is required to use the keyring, when it is passed in as
+    a keywork argument it is used as part of the ceph-osd command
+    """
+    path = '/var/lib/ceph/osd/%s-%s/' % (conf.cluster, osd_id)
+    monmap = os.path.join(path, 'activate.monmap')
+
+    system.chown(path)
+
+    base_command = [
+        'ceph-osd',
+        '--cluster', conf.cluster,
+        # undocumented flag, sets the `type` file to contain 'bluestore'
+        '--osd-objectstore', 'bluestore',
+        '--mkfs',
+        '-i', osd_id,
+        '--monmap', monmap,
+    ]
+
+    supplementary_command = [
+        '--osd-data', path,
+        '--osd-uuid', fsid,
+        '--setuser', 'ceph',
+        '--setgroup', 'ceph'
+    ]
+
+    if keyring is not None:
+        base_command.extend(['--key', keyring])
+
+    if wal:
+        base_command.extend(
+            ['--bluestore-block-wal-path', wal]
+        )
+        system.chown(wal)
+
+    if db:
+        base_command.extend(
+            ['--bluestore-block-db-path', db]
+        )
+        system.chown(db)
+
+    command = base_command + supplementary_command
+
+    process.run(command, obfuscate='--key')
+
+
+def osd_mkfs_filestore(osd_id, fsid):
+    """
+    Create the files for the OSD to function. A normal call will look like:
+
+          ceph-osd --cluster ceph --mkfs --mkkey -i 0 \
+                   --monmap /var/lib/ceph/osd/ceph-0/activate.monmap \
+                   --osd-data /var/lib/ceph/osd/ceph-0 \
+                   --osd-journal /var/lib/ceph/osd/ceph-0/journal \
+                   --osd-uuid 8d208665-89ae-4733-8888-5d3bfbeeec6c \
+                   --keyring /var/lib/ceph/osd/ceph-0/keyring \
+                   --setuser ceph --setgroup ceph
+
+    """
+    path = '/var/lib/ceph/osd/%s-%s/' % (conf.cluster, osd_id)
+    monmap = os.path.join(path, 'activate.monmap')
+    journal = os.path.join(path, 'journal')
+
+    system.chown(journal)
+    system.chown(path)
+
+    process.run([
+        'ceph-osd',
+        '--cluster', conf.cluster,
+        # undocumented flag, sets the `type` file to contain 'filestore'
+        '--osd-objectstore', 'filestore',
+        '--mkfs',
+        '-i', osd_id,
+        '--monmap', monmap,
+        '--osd-data', path,
+        '--osd-journal', journal,
+        '--osd-uuid', fsid,
+        '--setuser', 'ceph',
+        '--setgroup', 'ceph'
+    ])