Beispiel #1
0
def activate_filestore(lvs):
    # find the osd
    osd_lv = lvs.get(lv_tags={'ceph.type': 'data'})
    if not osd_lv:
        raise RuntimeError('Unable to find a data LV for filestore activation')
    is_encrypted = osd_lv.tags.get('ceph.encrypted', '0') == '1'

    osd_id = osd_lv.tags['ceph.osd_id']
    conf.cluster = osd_lv.tags['ceph.cluster_name']
    # it may have a volume with a journal
    osd_journal_lv = lvs.get(lv_tags={'ceph.type': 'journal'})
    # TODO: add sensible error reporting if this is ever the case
    # blow up with a KeyError if this doesn't exist
    osd_fsid = osd_lv.tags['ceph.osd_fsid']
    if not osd_journal_lv:
        # must be a disk partition, by quering blkid by the uuid we are ensuring that the
        # device path is always correct
        journal_uuid = osd_lv.tags['ceph.journal_uuid']
        osd_journal = disk.get_device_from_partuuid(journal_uuid)
    else:
        journal_uuid = osd_journal_lv.lv_uuid
        osd_journal = osd_lv.tags['ceph.journal_device']

    if not osd_journal:
        raise RuntimeError('unable to detect an lv or device journal for OSD %s' % osd_id)

    # this is done here, so that previous checks that ensure path availability
    # and correctness can still be enforced, and report if any issues are found
    if is_encrypted:
        lockbox_secret = osd_lv.tags['ceph.cephx_lockbox_secret']
        # this keyring writing is idempotent
        encryption_utils.write_lockbox_keyring(osd_id, osd_fsid, lockbox_secret)
        dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
        encryption_utils.luks_open(dmcrypt_secret, osd_lv.lv_path, osd_lv.lv_uuid)
        encryption_utils.luks_open(dmcrypt_secret, osd_journal, journal_uuid)

        osd_journal = '/dev/mapper/%s' % journal_uuid
        source = '/dev/mapper/%s' % osd_lv.lv_uuid
    else:
        source = osd_lv.lv_path
    # mount the osd
    destination = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
    if not system.device_is_mounted(source, destination=destination):
        process.run(['mount', '-v', source, destination])

    # always re-do the symlink regardless if it exists, so that the journal
    # device path that may have changed can be mapped correctly every time
    destination = '/var/lib/ceph/osd/%s-%s/journal' % (conf.cluster, osd_id)
    process.run(['ln', '-snf', osd_journal, destination])

    # make sure that the journal has proper permissions
    system.chown(osd_journal)

    # enable the ceph-volume unit for this OSD
    systemctl.enable_volume(osd_id, osd_fsid, 'lvm')

    # start the OSD
    systemctl.start_osd(osd_id)
    terminal.success("ceph-volume lvm activate successful for osd ID: %s" % osd_id)
Beispiel #2
0
def activate_bluestore(lvs):
    # find the osd
    osd_lv = lvs.get(lv_tags={'ceph.type': 'block'})
    is_encrypted = osd_lv.tags.get('ceph.encrypted', '0') == '1'
    dmcrypt_secret = None
    osd_id = osd_lv.tags['ceph.osd_id']
    conf.cluster = osd_lv.tags['ceph.cluster_name']
    osd_fsid = osd_lv.tags['ceph.osd_fsid']

    # mount on tmpfs the osd directory
    osd_path = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
    if not system.path_is_mounted(osd_path):
        # mkdir -p and mount as tmpfs
        prepare_utils.create_osd_path(osd_id, tmpfs=True)
    # XXX This needs to be removed once ceph-bluestore-tool can deal with
    # symlinks that exist in the osd dir
    for link_name in ['block', 'block.db', 'block.wal']:
        link_path = os.path.join(osd_path, link_name)
        if os.path.exists(link_path):
            os.unlink(os.path.join(osd_path, link_name))
    # encryption is handled here, before priming the OSD dir
    if is_encrypted:
        osd_lv_path = '/dev/mapper/%s' % osd_lv.lv_uuid
        lockbox_secret = osd_lv.tags['ceph.cephx_lockbox_secret']
        encryption_utils.write_lockbox_keyring(osd_id, osd_fsid, lockbox_secret)
        dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
        encryption_utils.luks_open(dmcrypt_secret, osd_lv.lv_path, osd_lv.lv_uuid)
    else:
        osd_lv_path = osd_lv.lv_path

    db_device_path = get_osd_device_path(osd_lv, lvs, 'db', dmcrypt_secret=dmcrypt_secret)
    wal_device_path = get_osd_device_path(osd_lv, lvs, 'wal', dmcrypt_secret=dmcrypt_secret)

    # Once symlinks are removed, the osd dir can be 'primed again.
    process.run([
        'ceph-bluestore-tool', '--cluster=%s' % conf.cluster,
        'prime-osd-dir', '--dev', osd_lv_path,
        '--path', osd_path])
    # always re-do the symlink regardless if it exists, so that the block,
    # block.wal, and block.db devices that may have changed can be mapped
    # correctly every time
    process.run(['ln', '-snf', osd_lv_path, os.path.join(osd_path, 'block')])
    system.chown(os.path.join(osd_path, 'block'))
    system.chown(osd_path)
    if db_device_path:
        destination = os.path.join(osd_path, 'block.db')
        process.run(['ln', '-snf', db_device_path, destination])
        system.chown(db_device_path)
    if wal_device_path:
        destination = os.path.join(osd_path, 'block.wal')
        process.run(['ln', '-snf', wal_device_path, destination])
        system.chown(wal_device_path)

    # enable the ceph-volume unit for this OSD
    systemctl.enable_volume(osd_id, osd_fsid, 'lvm')

    # start the OSD
    systemctl.start_osd(osd_id)
    terminal.success("ceph-volume lvm activate successful for osd ID: %s" % osd_id)
Beispiel #3
0
    def activate(self, args):
        with open(args.json_config, 'r') as fp:
            osd_metadata = json.load(fp)

        # Make sure that required devices are configured
        self.validate_devices(osd_metadata)

        osd_id = osd_metadata.get('whoami', args.osd_id)
        osd_fsid = osd_metadata.get('fsid', args.osd_fsid)
        data_uuid = osd_metadata.get('data', {}).get('uuid')
        conf.cluster = osd_metadata.get('cluster_name', 'ceph')
        if not data_uuid:
            raise RuntimeError(
                'Unable to activate OSD %s - no "uuid" key found for data' % args.osd_id
            )

        # Encryption detection, and capturing of the keys to decrypt
        self.is_encrypted = osd_metadata.get('encrypted', False)
        self.encryption_type = osd_metadata.get('encryption_type')
        if self.is_encrypted:
            lockbox_secret = osd_metadata.get('lockbox.keyring')
            # write the keyring always so that we can unlock
            encryption_utils.write_lockbox_keyring(osd_id, osd_fsid, lockbox_secret)
            # Store the secret around so that the decrypt method can reuse
            raw_dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
            # Note how both these calls need b64decode. For some reason, the
            # way ceph-disk creates these keys, it stores them in the monitor
            # *undecoded*, requiring this decode call again. The lvm side of
            # encryption doesn't need it, so we are assuming here that anything
            # that `simple` scans, will come from ceph-disk and will need this
            # extra decode call here
            self.dmcrypt_secret = base64.b64decode(raw_dmcrypt_secret)

        cluster_name = osd_metadata.get('cluster_name', 'ceph')
        osd_dir = '/var/lib/ceph/osd/%s-%s' % (cluster_name, osd_id)

        # XXX there is no support for LVM here
        data_device = self.get_device(data_uuid)
        journal_device = self.get_device(osd_metadata.get('journal', {}).get('uuid'))
        block_device = self.get_device(osd_metadata.get('block', {}).get('uuid'))
        block_db_device = self.get_device(osd_metadata.get('block.db', {}).get('uuid'))
        block_wal_device = self.get_device(osd_metadata.get('block.wal', {}).get('uuid'))

        if not system.device_is_mounted(data_device, destination=osd_dir):
            process.run(['mount', '-v', data_device, osd_dir])

        device_map = {
            'journal': journal_device,
            'block': block_device,
            'block.db': block_db_device,
            'block.wal': block_wal_device
        }

        for name, device in device_map.items():
            if not device:
                continue
            # always re-do the symlink regardless if it exists, so that the journal
            # device path that may have changed can be mapped correctly every time
            destination = os.path.join(osd_dir, name)
            process.run(['ln', '-snf', device, destination])

            # make sure that the journal has proper permissions
            system.chown(device)

        self.enable_systemd_units(osd_id, osd_fsid)

        terminal.success('Successfully activated OSD %s with FSID %s' % (osd_id, osd_fsid))
Beispiel #4
0
    def scan_encrypted(self, directory=None):
        device = self.encryption_metadata['device']
        lockbox = self.encryption_metadata['lockbox']
        encryption_type = self.encryption_metadata['type']
        osd_metadata = {}
        # Get the PARTUUID of the device to make sure have the right one and
        # that maps to the data device
        device_uuid = disk.get_partuuid(device)
        dm_path = '/dev/mapper/%s' % device_uuid
        # check if this partition is already mapped
        device_status = encryption.status(device_uuid)

        # capture all the information from the lockbox first, reusing the
        # directory scan method
        if self.device_mounts.get(lockbox):
            lockbox_path = self.device_mounts.get(lockbox)[0]
            lockbox_metadata = self.scan_directory(lockbox_path)
            # ceph-disk stores the fsid as osd-uuid in the lockbox, thanks ceph-disk
            dmcrypt_secret = encryption.get_dmcrypt_key(
                None,  # There is no ID stored in the lockbox
                lockbox_metadata['osd-uuid'],
                os.path.join(lockbox_path, 'keyring')
            )
        else:
            with system.tmp_mount(lockbox) as lockbox_path:
                lockbox_metadata = self.scan_directory(lockbox_path)
                # ceph-disk stores the fsid as osd-uuid in the lockbox, thanks ceph-disk
                dmcrypt_secret = encryption.get_dmcrypt_key(
                    None,  # There is no ID stored in the lockbox
                    lockbox_metadata['osd-uuid'],
                    os.path.join(lockbox_path, 'keyring')
                )

        if not device_status:
            # Note how both these calls need b64decode. For some reason, the
            # way ceph-disk creates these keys, it stores them in the monitor
            # *undecoded*, requiring this decode call again. The lvm side of
            # encryption doesn't need it, so we are assuming here that anything
            # that `simple` scans, will come from ceph-disk and will need this
            # extra decode call here
            dmcrypt_secret = base64.b64decode(dmcrypt_secret)
            if encryption_type == 'luks':
                encryption.luks_open(dmcrypt_secret, device, device_uuid)
            else:
                encryption.plain_open(dmcrypt_secret, device, device_uuid)

        # If we have a directory, use that instead of checking for mounts
        if directory:
            osd_metadata = self.scan_directory(directory)
        else:
            # Now check if that mapper is mounted already, to avoid remounting and
            # decrypting the device
            dm_path_mount = self.device_mounts.get(dm_path)
            if dm_path_mount:
                osd_metadata = self.scan_directory(dm_path_mount[0])
            else:
                with system.tmp_mount(dm_path, encrypted=True) as device_path:
                    osd_metadata = self.scan_directory(device_path)

        osd_metadata['encrypted'] = True
        osd_metadata['encryption_type'] = encryption_type
        osd_metadata['lockbox.keyring'] = parse_keyring(lockbox_metadata['keyring'])
        return osd_metadata
Beispiel #5
0
def activate_filestore(lvs, no_systemd=False):
    # find the osd
    osd_lv = lvs.get(lv_tags={'ceph.type': 'data'})
    if not osd_lv:
        raise RuntimeError('Unable to find a data LV for filestore activation')
    is_encrypted = osd_lv.tags.get('ceph.encrypted', '0') == '1'
    is_vdo = osd_lv.tags.get('ceph.vdo', '0')

    osd_id = osd_lv.tags['ceph.osd_id']
    conf.cluster = osd_lv.tags['ceph.cluster_name']
    # it may have a volume with a journal
    osd_journal_lv = lvs.get(lv_tags={'ceph.type': 'journal'})
    # TODO: add sensible error reporting if this is ever the case
    # blow up with a KeyError if this doesn't exist
    osd_fsid = osd_lv.tags['ceph.osd_fsid']
    if not osd_journal_lv:
        # must be a disk partition, by quering blkid by the uuid we are ensuring that the
        # device path is always correct
        journal_uuid = osd_lv.tags['ceph.journal_uuid']
        osd_journal = disk.get_device_from_partuuid(journal_uuid)
    else:
        journal_uuid = osd_journal_lv.lv_uuid
        osd_journal = osd_lv.tags['ceph.journal_device']

    if not osd_journal:
        raise RuntimeError(
            'unable to detect an lv or device journal for OSD %s' % osd_id)

    # this is done here, so that previous checks that ensure path availability
    # and correctness can still be enforced, and report if any issues are found
    if is_encrypted:
        lockbox_secret = osd_lv.tags['ceph.cephx_lockbox_secret']
        # this keyring writing is idempotent
        encryption_utils.write_lockbox_keyring(osd_id, osd_fsid,
                                               lockbox_secret)
        dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
        encryption_utils.luks_open(dmcrypt_secret, osd_lv.lv_path,
                                   osd_lv.lv_uuid)
        encryption_utils.luks_open(dmcrypt_secret, osd_journal, journal_uuid)

        osd_journal = '/dev/mapper/%s' % journal_uuid
        source = '/dev/mapper/%s' % osd_lv.lv_uuid
    else:
        source = osd_lv.lv_path

    # mount the osd
    destination = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
    if not system.device_is_mounted(source, destination=destination):
        prepare_utils.mount_osd(source, osd_id, is_vdo=is_vdo)

    # always re-do the symlink regardless if it exists, so that the journal
    # device path that may have changed can be mapped correctly every time
    destination = '/var/lib/ceph/osd/%s-%s/journal' % (conf.cluster, osd_id)
    process.run(['ln', '-snf', osd_journal, destination])

    # make sure that the journal has proper permissions
    system.chown(osd_journal)

    if no_systemd is False:
        # enable the ceph-volume unit for this OSD
        systemctl.enable_volume(osd_id, osd_fsid, 'lvm')

        # start the OSD
        systemctl.start_osd(osd_id)
    terminal.success("ceph-volume lvm activate successful for osd ID: %s" %
                     osd_id)
Beispiel #6
0
def activate_bluestore(lvs, no_systemd=False):
    # find the osd
    osd_lv = lvs.get(lv_tags={'ceph.type': 'block'})
    if not osd_lv:
        raise RuntimeError('could not find a bluestore OSD to activate')
    is_encrypted = osd_lv.tags.get('ceph.encrypted', '0') == '1'
    dmcrypt_secret = None
    osd_id = osd_lv.tags['ceph.osd_id']
    conf.cluster = osd_lv.tags['ceph.cluster_name']
    osd_fsid = osd_lv.tags['ceph.osd_fsid']

    # mount on tmpfs the osd directory
    osd_path = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
    if not system.path_is_mounted(osd_path):
        # mkdir -p and mount as tmpfs
        prepare_utils.create_osd_path(osd_id, tmpfs=True)
    # XXX This needs to be removed once ceph-bluestore-tool can deal with
    # symlinks that exist in the osd dir
    for link_name in ['block', 'block.db', 'block.wal']:
        link_path = os.path.join(osd_path, link_name)
        if os.path.exists(link_path):
            os.unlink(os.path.join(osd_path, link_name))
    # encryption is handled here, before priming the OSD dir
    if is_encrypted:
        osd_lv_path = '/dev/mapper/%s' % osd_lv.lv_uuid
        lockbox_secret = osd_lv.tags['ceph.cephx_lockbox_secret']
        encryption_utils.write_lockbox_keyring(osd_id, osd_fsid,
                                               lockbox_secret)
        dmcrypt_secret = encryption_utils.get_dmcrypt_key(osd_id, osd_fsid)
        encryption_utils.luks_open(dmcrypt_secret, osd_lv.lv_path,
                                   osd_lv.lv_uuid)
    else:
        osd_lv_path = osd_lv.lv_path

    db_device_path = get_osd_device_path(osd_lv,
                                         lvs,
                                         'db',
                                         dmcrypt_secret=dmcrypt_secret)
    wal_device_path = get_osd_device_path(osd_lv,
                                          lvs,
                                          'wal',
                                          dmcrypt_secret=dmcrypt_secret)

    # Once symlinks are removed, the osd dir can be 'primed again.
    process.run([
        'ceph-bluestore-tool',
        '--cluster=%s' % conf.cluster, 'prime-osd-dir', '--dev', osd_lv_path,
        '--path', osd_path, '--no-mon-config'
    ])
    # always re-do the symlink regardless if it exists, so that the block,
    # block.wal, and block.db devices that may have changed can be mapped
    # correctly every time
    process.run(['ln', '-snf', osd_lv_path, os.path.join(osd_path, 'block')])
    system.chown(os.path.join(osd_path, 'block'))
    system.chown(osd_path)
    if db_device_path:
        destination = os.path.join(osd_path, 'block.db')
        process.run(['ln', '-snf', db_device_path, destination])
        system.chown(db_device_path)
        system.chown(destination)
    if wal_device_path:
        destination = os.path.join(osd_path, 'block.wal')
        process.run(['ln', '-snf', wal_device_path, destination])
        system.chown(wal_device_path)
        system.chown(destination)

    if no_systemd is False:
        # enable the ceph-volume unit for this OSD
        systemctl.enable_volume(osd_id, osd_fsid, 'lvm')

        # start the OSD
        systemctl.start_osd(osd_id)
    terminal.success("ceph-volume lvm activate successful for osd ID: %s" %
                     osd_id)
Beispiel #7
0
    def scan_encrypted(self, directory=None):
        device = self.encryption_metadata['device']
        lockbox = self.encryption_metadata['lockbox']
        encryption_type = self.encryption_metadata['type']
        osd_metadata = {}
        # Get the PARTUUID of the device to make sure have the right one and
        # that maps to the data device
        device_uuid = disk.get_partuuid(device)
        dm_path = '/dev/mapper/%s' % device_uuid
        # check if this partition is already mapped
        device_status = encryption.status(device_uuid)

        # capture all the information from the lockbox first, reusing the
        # directory scan method
        if self.device_mounts.get(lockbox):
            lockbox_path = self.device_mounts.get(lockbox)[0]
            lockbox_metadata = self.scan_directory(lockbox_path)
            # ceph-disk stores the fsid as osd-uuid in the lockbox, thanks ceph-disk
            dmcrypt_secret = encryption.get_dmcrypt_key(
                None,  # There is no ID stored in the lockbox
                lockbox_metadata['osd-uuid'],
                os.path.join(lockbox_path, 'keyring'))
        else:
            with system.tmp_mount(lockbox) as lockbox_path:
                lockbox_metadata = self.scan_directory(lockbox_path)
                # ceph-disk stores the fsid as osd-uuid in the lockbox, thanks ceph-disk
                dmcrypt_secret = encryption.get_dmcrypt_key(
                    None,  # There is no ID stored in the lockbox
                    lockbox_metadata['osd-uuid'],
                    os.path.join(lockbox_path, 'keyring'))

        if not device_status:
            # Note how both these calls need b64decode. For some reason, the
            # way ceph-disk creates these keys, it stores them in the monitor
            # *undecoded*, requiring this decode call again. The lvm side of
            # encryption doesn't need it, so we are assuming here that anything
            # that `simple` scans, will come from ceph-disk and will need this
            # extra decode call here
            dmcrypt_secret = base64.b64decode(dmcrypt_secret)
            if encryption_type == 'luks':
                encryption.luks_open(dmcrypt_secret, device, device_uuid)
            else:
                encryption.plain_open(dmcrypt_secret, device, device_uuid)

        # If we have a directory, use that instead of checking for mounts
        if directory:
            osd_metadata = self.scan_directory(directory)
        else:
            # Now check if that mapper is mounted already, to avoid remounting and
            # decrypting the device
            dm_path_mount = self.device_mounts.get(dm_path)
            if dm_path_mount:
                osd_metadata = self.scan_directory(dm_path_mount[0])
            else:
                with system.tmp_mount(dm_path, encrypted=True) as device_path:
                    osd_metadata = self.scan_directory(device_path)

        osd_metadata['encrypted'] = True
        osd_metadata['encryption_type'] = encryption_type
        osd_metadata['lockbox.keyring'] = parse_keyring(
            lockbox_metadata['keyring'])
        return osd_metadata