from __future__ import print_function
import json
import logging
+import os
from textwrap import dedent
from ceph_volume.util import prepare as prepare_utils
+from ceph_volume.util import encryption as encryption_utils
+from ceph_volume.util import disk
from ceph_volume.util import system
-from ceph_volume import conf, decorators, terminal
+from ceph_volume import decorators, terminal
from ceph_volume.devices.lvm.common import rollback_osd
from .common import create_parser
logger = logging.getLogger(__name__)
+def prepare_dmcrypt(key, device, device_type, fsid):
+ """
+ Helper for devices that are encrypted. The operations needed for
+ block, db, wal, or data/journal devices are all the same
+ """
+ if not device:
+ return ''
+ kname = disk.lsblk(device)['KNAME']
+ mapping = 'ceph-{}-{}-{}-dmcrypt'.format(fsid, kname, device_type)
+ # format data device
+ encryption_utils.luks_format(
+ key,
+ device
+ )
+ encryption_utils.luks_open(
+ key,
+ device,
+ mapping
+ )
+
+ return '/dev/mapper/{}'.format(mapping)
def prepare_bluestore(block, wal, db, secrets, osd_id, fsid, tmpfs):
"""
"""
cephx_secret = secrets.get('cephx_secret', prepare_utils.create_key())
+ if secrets.get('dmcrypt_key'):
+ key = secrets['dmcrypt_key']
+ block = prepare_dmcrypt(key, block, 'block', fsid)
+ wal = prepare_dmcrypt(key, wal, 'wal', fsid)
+ db = prepare_dmcrypt(key, db, 'db', fsid)
+
# create the directory
prepare_utils.create_osd_path(osd_id, tmpfs=tmpfs)
# symlink the block
logger.info('will rollback OSD ID creation')
rollback_osd(self.args, self.osd_id)
raise
- terminal.success("ceph-volume raw prepare successful for: %s" % self.args.data)
-
- def get_cluster_fsid(self):
- """
- Allows using --cluster-fsid as an argument, but can fallback to reading
- from ceph.conf if that is unset (the default behavior).
- """
- if self.args.cluster_fsid:
- return self.args.cluster_fsid
+ dmcrypt_log = 'dmcrypt' if args.dmcrypt else 'clear'
+ terminal.success("ceph-volume raw {} prepare successful for: {}".format(dmcrypt_log, self.args.data))
- return conf.ceph.get('global', 'fsid')
@decorators.needs_root
def prepare(self):
secrets = {'cephx_secret': prepare_utils.create_key()}
+ encrypted = 1 if self.args.dmcrypt else 0
+ cephx_lockbox_secret = '' if not encrypted else prepare_utils.create_key()
+
+ if encrypted:
+ secrets['dmcrypt_key'] = os.getenv('CEPH_VOLUME_DMCRYPT_SECRET')
+ secrets['cephx_lockbox_secret'] = cephx_lockbox_secret # dummy value to make `ceph osd new` not complaining
+
osd_fsid = system.generate_uuid()
crush_device_class = self.args.crush_device_class
if crush_device_class:
# reuse a given ID if it exists, otherwise create a new ID
self.osd_id = prepare_utils.create_id(
osd_fsid, json.dumps(secrets))
+
prepare_bluestore(
self.args.data,
wal,
Once the OSD is ready, an ad-hoc systemd unit will be enabled so that
it can later get activated and the OSD daemon can get started.
- Encryption is not supported.
-
ceph-volume raw prepare --bluestore --data {device}
DB and WAL devices are supported.
if not self.args.bluestore:
terminal.error('must specify --bluestore (currently the only supported backend)')
raise SystemExit(1)
+ if self.args.dmcrypt and not os.getenv('CEPH_VOLUME_DMCRYPT_SECRET'):
+ terminal.error('encryption was requested (--dmcrypt) but environment variable ' \
+ 'CEPH_VOLUME_DMCRYPT_SECRET is not set, you must set ' \
+ 'this variable to provide a dmcrypt secret.')
+ raise SystemExit(1)
self.safe_prepare(self.args)