Beispiel #1
0
    def setup_device(self, device_type, device_name, tags):
        """
        Check if ``device`` is an lv, if so, set the tags, making sure to
        update the tags with the lv_uuid and lv_path which the incoming tags
        will not have.

        If the device is not a logical volume, then retrieve the partition UUID
        by querying ``blkid``
        """
        if device_name is None:
            return '', '', tags
        tags['ceph.type'] = device_type
        tags['ceph.vdo'] = api.is_vdo(device_name)
        lv = self.get_lv(device_name)
        if lv:
            uuid = lv.lv_uuid
            path = lv.lv_path
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
            lv.set_tags(tags)
        else:
            # otherwise assume this is a regular disk partition
            uuid = self.get_ptuuid(device_name)
            path = device_name
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
        return path, uuid, tags
Beispiel #2
0
    def setup_device(self, device_type, device_name, tags):
        """
        Check if ``device`` is an lv, if so, set the tags, making sure to
        update the tags with the lv_uuid and lv_path which the incoming tags
        will not have.

        If the device is not a logical volume, then retrieve the partition UUID
        by querying ``blkid``
        """
        if device_name is None:
            return '', '', tags
        tags['ceph.type'] = device_type
        tags['ceph.vdo'] = api.is_vdo(device_name)
        lv = self.get_lv(device_name)
        if lv:
            uuid = lv.lv_uuid
            path = lv.lv_path
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
            lv.set_tags(tags)
        else:
            # otherwise assume this is a regular disk partition
            uuid = self.get_ptuuid(device_name)
            path = device_name
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
        return path, uuid, tags
Beispiel #3
0
    def setup_device(self, device_type, device_name, tags, size, slots):
        """
        Check if ``device`` is an lv, if so, set the tags, making sure to
        update the tags with the lv_uuid and lv_path which the incoming tags
        will not have.

        If the device is not a logical volume, then retrieve the partition UUID
        by querying ``blkid``
        """
        if device_name is None:
            return '', '', tags
        tags['ceph.type'] = device_type
        tags['ceph.vdo'] = api.is_vdo(device_name)

        try:
            vg_name, lv_name = device_name.split('/')
            lv = api.get_first_lv(filters={'lv_name': lv_name,
                                           'vg_name': vg_name})
        except ValueError:
            lv = None

        if lv:
            uuid = lv.lv_uuid
            path = lv.lv_path
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
            lv.set_tags(tags)
        elif disk.is_device(device_name):
            # We got a disk, create an lv
            lv_type = "osd-{}".format(device_type)
            uuid = system.generate_uuid()
            tags['ceph.{}_uuid'.format(device_type)] = uuid
            kwargs = {
                'device': device_name,
                'tags': tags,
                'slots': slots
            }
            #TODO use get_block_db_size and co here to get configured size in
            #conf file
            if size != 0:
                kwargs['size'] = size
            lv = api.create_lv(
                lv_type,
                uuid,
                **kwargs)
            path = lv.lv_path
            tags['ceph.{}_device'.format(device_type)] = path
            lv.set_tags(tags)
        else:
            # otherwise assume this is a regular disk partition
            uuid = self.get_ptuuid(device_name)
            path = device_name
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
        return path, uuid, tags
Beispiel #4
0
    def setup_device(self, device_type, device_name, tags, size):
        """
        Check if ``device`` is an lv, if so, set the tags, making sure to
        update the tags with the lv_uuid and lv_path which the incoming tags
        will not have.

        If the device is not a logical volume, then retrieve the partition UUID
        by querying ``blkid``
        """
        if device_name is None:
            return '', '', tags
        tags['ceph.type'] = device_type
        tags['ceph.vdo'] = api.is_vdo(device_name)
        lv = self.get_lv(device_name)
        if lv:
            uuid = lv.lv_uuid
            path = lv.lv_path
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
            lv.set_tags(tags)
        elif disk.is_device(device_name):
            # We got a disk, create an lv
            lv_type = "osd-{}".format(device_type)
            uuid = system.generate_uuid()
            tags['ceph.{}_uuid'.format(device_type)] = uuid
            kwargs = {
                'device':
                device_name,
                'tags':
                tags,
                'slots':
                getattr(self.args, 'block_{}_slots'.format(device_type), 1),
            }
            if size != 0:
                kwargs['size'] = disk.Size.parse(size)
            lv = api.create_lv(lv_type, uuid, **kwargs)
            path = lv.lv_path
            tags['ceph.{}_device'.format(device_type)] = path
            lv.set_tags(tags)
        else:
            # otherwise assume this is a regular disk partition
            uuid = self.get_ptuuid(device_name)
            path = device_name
            tags['ceph.%s_uuid' % device_type] = uuid
            tags['ceph.%s_device' % device_type] = path
        return path, uuid, tags
Beispiel #5
0
def prepare_filestore(device, journal, secrets, tags, osd_id, fsid):
    """
    :param device: The name of the logical volume to work with
    :param journal: similar to device but can also be a regular/plain disk
    :param secrets: A dict with the secrets needed to create the osd (e.g. cephx)
    :param id_: The OSD id
    :param fsid: The OSD fsid, also known as the OSD UUID
    """
    cephx_secret = secrets.get('cephx_secret', prepare_utils.create_key())

    # encryption-only operations
    if secrets.get('dmcrypt_key'):
        # format and open ('decrypt' devices) and re-assign the device and journal
        # variables so that the rest of the process can use the mapper paths
        key = secrets['dmcrypt_key']
        device = prepare_dmcrypt(key, device, 'data', tags)
        journal = prepare_dmcrypt(key, journal, 'journal', tags)

    # vdo detection
    is_vdo = api.is_vdo(device)
    # create the directory
    prepare_utils.create_osd_path(osd_id)
    # format the device
    prepare_utils.format_device(device)
    # mount the data device
    prepare_utils.mount_osd(device, osd_id, is_vdo=is_vdo)
    # 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_filestore(osd_id, fsid, cephx_secret)
    # write the OSD keyring if it doesn't exist already
    prepare_utils.write_keyring(osd_id, cephx_secret)
    if secrets.get('dmcrypt_key'):
        # if the device is going to get activated right away, this can be done
        # here, otherwise it will be recreated
        encryption_utils.write_lockbox_keyring(
            osd_id,
            fsid,
            tags['ceph.cephx_lockbox_secret']
        )
Beispiel #6
0
def prepare_filestore(device, journal, secrets, tags, osd_id, fsid):
    """
    :param device: The name of the logical volume to work with
    :param journal: similar to device but can also be a regular/plain disk
    :param secrets: A dict with the secrets needed to create the osd (e.g. cephx)
    :param id_: The OSD id
    :param fsid: The OSD fsid, also known as the OSD UUID
    """
    cephx_secret = secrets.get('cephx_secret', prepare_utils.create_key())

    # encryption-only operations
    if secrets.get('dmcrypt_key'):
        # format and open ('decrypt' devices) and re-assign the device and journal
        # variables so that the rest of the process can use the mapper paths
        key = secrets['dmcrypt_key']
        device = prepare_dmcrypt(key, device, 'data', tags)
        journal = prepare_dmcrypt(key, journal, 'journal', tags)

    # vdo detection
    is_vdo = api.is_vdo(device)
    # create the directory
    prepare_utils.create_osd_path(osd_id)
    # format the device
    prepare_utils.format_device(device)
    # mount the data device
    prepare_utils.mount_osd(device, osd_id, is_vdo=is_vdo)
    # 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_filestore(osd_id, fsid, cephx_secret)
    # write the OSD keyring if it doesn't exist already
    prepare_utils.write_keyring(osd_id, cephx_secret)
    if secrets.get('dmcrypt_key'):
        # if the device is going to get activated right away, this can be done
        # here, otherwise it will be recreated
        encryption_utils.write_lockbox_keyring(
            osd_id,
            fsid,
            tags['ceph.cephx_lockbox_secret']
        )
Beispiel #7
0
 def test_is_vdo_returns_a_string(self, monkeypatch):
     monkeypatch.setattr('ceph_volume.api.lvm._is_vdo',
                         lambda x, **kw: True)
     assert api.is_vdo('/path') == '1'
Beispiel #8
0
    def test_exceptions_return_false(self, monkeypatch):
        def throw():
            raise Exception()

        monkeypatch.setattr('ceph_volume.api.lvm._is_vdo', throw)
        assert api.is_vdo('/path') == '0'
Beispiel #9
0
 def test_is_vdo_returns_a_string(self, monkeypatch):
     monkeypatch.setattr('ceph_volume.api.lvm._is_vdo', lambda x: True)
     assert api.is_vdo('/path') == '1'
Beispiel #10
0
 def test_exceptions_return_false(self, monkeypatch):
     def throw():
         raise Exception()
     monkeypatch.setattr('ceph_volume.api.lvm._is_vdo', throw)
     assert api.is_vdo('/path') == '0'
Beispiel #11
0
    def prepare(self, args):
        # FIXME we don't allow re-using a keyring, we always generate one for the
        # OSD, this needs to be fixed. This could either be a file (!) or a string
        # (!!) or some flags that we would need to compound into a dict so that we
        # can convert to JSON (!!!)
        secrets = {'cephx_secret': prepare_utils.create_key()}
        cephx_lockbox_secret = ''
        encrypted = 1 if args.dmcrypt else 0
        cephx_lockbox_secret = '' if not encrypted else prepare_utils.create_key(
        )

        if encrypted:
            secrets['dmcrypt_key'] = encryption_utils.create_dmcrypt_key()
            secrets['cephx_lockbox_secret'] = cephx_lockbox_secret

        cluster_fsid = conf.ceph.get('global', 'fsid')
        osd_fsid = args.osd_fsid or system.generate_uuid()
        crush_device_class = args.crush_device_class
        if crush_device_class:
            secrets['crush_device_class'] = 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),
                                              osd_id=args.osd_id)
        tags = {
            'ceph.osd_fsid': osd_fsid,
            'ceph.osd_id': self.osd_id,
            'ceph.cluster_fsid': cluster_fsid,
            'ceph.cluster_name': conf.cluster,
            'ceph.crush_device_class': crush_device_class,
        }
        if args.filestore:
            if not args.journal:
                raise RuntimeError(
                    '--journal is required when using --filestore')

            data_lv = self.get_lv(args.data)
            if not data_lv:
                data_lv = self.prepare_device(args.data, 'data', cluster_fsid,
                                              osd_fsid)

            tags['ceph.data_device'] = data_lv.lv_path
            tags['ceph.data_uuid'] = data_lv.lv_uuid
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted
            tags['ceph.vdo'] = api.is_vdo(data_lv.lv_path)

            journal_device, journal_uuid, tags = self.setup_device(
                'journal', args.journal, tags)

            tags['ceph.type'] = 'data'
            data_lv.set_tags(tags)

            prepare_filestore(
                data_lv.lv_path,
                journal_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )
        elif args.bluestore:
            block_lv = self.get_lv(args.data)
            if not block_lv:
                block_lv = self.prepare_device(args.data, 'block',
                                               cluster_fsid, osd_fsid)

            tags['ceph.block_device'] = block_lv.lv_path
            tags['ceph.block_uuid'] = block_lv.lv_uuid
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted
            tags['ceph.vdo'] = api.is_vdo(block_lv.lv_path)

            wal_device, wal_uuid, tags = self.setup_device(
                'wal', args.block_wal, tags)
            db_device, db_uuid, tags = self.setup_device(
                'db', args.block_db, tags)

            tags['ceph.type'] = 'block'
            block_lv.set_tags(tags)

            prepare_bluestore(
                block_lv.lv_path,
                wal_device,
                db_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )
Beispiel #12
0
    def prepare(self):
        # FIXME we don't allow re-using a keyring, we always generate one for the
        # OSD, this needs to be fixed. This could either be a file (!) or a string
        # (!!) or some flags that we would need to compound into a dict so that we
        # can convert to JSON (!!!)
        secrets = {'cephx_secret': prepare_utils.create_key()}
        cephx_lockbox_secret = ''
        encrypted = 1 if self.args.dmcrypt else 0
        cephx_lockbox_secret = '' if not encrypted else prepare_utils.create_key(
        )

        if encrypted:
            secrets['dmcrypt_key'] = encryption_utils.create_dmcrypt_key()
            secrets['cephx_lockbox_secret'] = cephx_lockbox_secret

        cluster_fsid = self.get_cluster_fsid()

        osd_fsid = self.args.osd_fsid or system.generate_uuid()
        crush_device_class = self.args.crush_device_class
        if crush_device_class:
            secrets['crush_device_class'] = 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),
                                              osd_id=self.args.osd_id)
        tags = {
            'ceph.osd_fsid': osd_fsid,
            'ceph.osd_id': self.osd_id,
            'ceph.cluster_fsid': cluster_fsid,
            'ceph.cluster_name': conf.cluster,
            'ceph.crush_device_class': crush_device_class,
            'ceph.osdspec_affinity': prepare_utils.get_osdspec_affinity()
        }
        if self.args.filestore:
            if not self.args.journal:
                logger.info(('no journal was specifed, creating journal lv '
                             'on {}').format(self.args.data))
                self.args.journal = self.args.data
                self.args.journal_size = disk.Size(g=5)
                # need to adjust data size/slots for colocated journal
                if self.args.data_size:
                    self.args.data_size -= self.args.journal_size
                if self.args.data_slots == 1:
                    self.args.data_slots = 0
                else:
                    raise RuntimeError('Can\'t handle multiple filestore OSDs '
                                       'with colocated journals yet. Please '
                                       'create journal LVs manually')
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted

            journal_device, journal_uuid, tags = self.setup_device(
                'journal', self.args.journal, tags, self.args.journal_size,
                self.args.journal_slots)

            try:
                vg_name, lv_name = self.args.data.split('/')
                data_lv = api.get_single_lv(filters={
                    'lv_name': lv_name,
                    'vg_name': vg_name
                })
            except ValueError:
                data_lv = None

            if not data_lv:
                data_lv = self.prepare_data_device('data', osd_fsid)

            tags['ceph.data_device'] = data_lv.lv_path
            tags['ceph.data_uuid'] = data_lv.lv_uuid
            tags['ceph.vdo'] = api.is_vdo(data_lv.lv_path)
            tags['ceph.type'] = 'data'
            data_lv.set_tags(tags)
            if not journal_device.startswith('/'):
                # we got a journal lv, set rest of the tags
                api.get_single_lv(filters={
                    'lv_name': lv_name,
                    'vg_name': vg_name
                }).set_tags(tags)

            prepare_filestore(
                data_lv.lv_path,
                journal_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )
        elif self.args.bluestore:
            try:
                vg_name, lv_name = self.args.data.split('/')
                block_lv = api.get_single_lv(filters={
                    'lv_name': lv_name,
                    'vg_name': vg_name
                })
            except ValueError:
                block_lv = None

            if not block_lv:
                block_lv = self.prepare_data_device('block', osd_fsid)

            tags['ceph.block_device'] = block_lv.lv_path
            tags['ceph.block_uuid'] = block_lv.lv_uuid
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted
            tags['ceph.vdo'] = api.is_vdo(block_lv.lv_path)

            wal_device, wal_uuid, tags = self.setup_device(
                'wal', self.args.block_wal, tags, self.args.block_wal_size,
                self.args.block_wal_slots)
            db_device, db_uuid, tags = self.setup_device(
                'db', self.args.block_db, tags, self.args.block_db_size,
                self.args.block_db_slots)

            tags['ceph.type'] = 'block'
            block_lv.set_tags(tags)

            prepare_bluestore(
                block_lv.lv_path,
                wal_device,
                db_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )
Beispiel #13
0
    def prepare(self, args):
        # FIXME we don't allow re-using a keyring, we always generate one for the
        # OSD, this needs to be fixed. This could either be a file (!) or a string
        # (!!) or some flags that we would need to compound into a dict so that we
        # can convert to JSON (!!!)
        secrets = {'cephx_secret': prepare_utils.create_key()}
        cephx_lockbox_secret = ''
        encrypted = 1 if args.dmcrypt else 0
        cephx_lockbox_secret = '' if not encrypted else prepare_utils.create_key()

        if encrypted:
            secrets['dmcrypt_key'] = encryption_utils.create_dmcrypt_key()
            secrets['cephx_lockbox_secret'] = cephx_lockbox_secret

        cluster_fsid = conf.ceph.get('global', 'fsid')
        osd_fsid = args.osd_fsid or system.generate_uuid()
        crush_device_class = args.crush_device_class
        if crush_device_class:
            secrets['crush_device_class'] = 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), osd_id=args.osd_id)
        tags = {
            'ceph.osd_fsid': osd_fsid,
            'ceph.osd_id': self.osd_id,
            'ceph.cluster_fsid': cluster_fsid,
            'ceph.cluster_name': conf.cluster,
            'ceph.crush_device_class': crush_device_class,
        }
        if args.filestore:
            if not args.journal:
                raise RuntimeError('--journal is required when using --filestore')

            data_lv = self.get_lv(args.data)
            if not data_lv:
                data_lv = self.prepare_device(args.data, 'data', cluster_fsid, osd_fsid)

            tags['ceph.data_device'] = data_lv.lv_path
            tags['ceph.data_uuid'] = data_lv.lv_uuid
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted
            tags['ceph.vdo'] = api.is_vdo(data_lv.lv_path)

            journal_device, journal_uuid, tags = self.setup_device('journal', args.journal, tags)

            tags['ceph.type'] = 'data'
            data_lv.set_tags(tags)

            prepare_filestore(
                data_lv.lv_path,
                journal_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )
        elif args.bluestore:
            block_lv = self.get_lv(args.data)
            if not block_lv:
                block_lv = self.prepare_device(args.data, 'block', cluster_fsid, osd_fsid)

            tags['ceph.block_device'] = block_lv.lv_path
            tags['ceph.block_uuid'] = block_lv.lv_uuid
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted
            tags['ceph.vdo'] = api.is_vdo(block_lv.lv_path)

            wal_device, wal_uuid, tags = self.setup_device('wal', args.block_wal, tags)
            db_device, db_uuid, tags = self.setup_device('db', args.block_db, tags)

            tags['ceph.type'] = 'block'
            block_lv.set_tags(tags)

            prepare_bluestore(
                block_lv.lv_path,
                wal_device,
                db_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )
Beispiel #14
0
    def prepare(self):
        # FIXME we don't allow re-using a keyring, we always generate one for the
        # OSD, this needs to be fixed. This could either be a file (!) or a string
        # (!!) or some flags that we would need to compound into a dict so that we
        # can convert to JSON (!!!)
        secrets = {'cephx_secret': prepare_utils.create_key()}
        cephx_lockbox_secret = ''
        encrypted = 1 if self.args.dmcrypt else 0
        cephx_lockbox_secret = '' if not encrypted else prepare_utils.create_key()

        if encrypted:
            secrets['dmcrypt_key'] = encryption_utils.create_dmcrypt_key()
            secrets['cephx_lockbox_secret'] = cephx_lockbox_secret

        cluster_fsid = self.get_cluster_fsid()

        osd_fsid = self.args.osd_fsid or system.generate_uuid()
        crush_device_class = self.args.crush_device_class
        if crush_device_class:
            secrets['crush_device_class'] = 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), osd_id=self.args.osd_id)
        tags = {
            'ceph.osd_fsid': osd_fsid,
            'ceph.osd_id': self.osd_id,
            'ceph.cluster_fsid': cluster_fsid,
            'ceph.cluster_name': conf.cluster,
            'ceph.crush_device_class': crush_device_class,
            'ceph.osdspec_affinity': prepare_utils.get_osdspec_affinity()
        }
        if self.args.filestore:
            #TODO: allow auto creation of journal on passed device, only works
            # when physical device is passed, not LV
            if not self.args.journal:
                raise RuntimeError('--journal is required when using --filestore')

            try:
                vg_name, lv_name = self.args.data.split('/')
                data_lv = api.get_first_lv(filters={'lv_name': lv_name,
                                                    'vg_name': vg_name})
            except ValueError:
                data_lv = None

            if not data_lv:
                data_lv = self.prepare_data_device('data', osd_fsid)

            tags['ceph.data_device'] = data_lv.lv_path
            tags['ceph.data_uuid'] = data_lv.lv_uuid
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted
            tags['ceph.vdo'] = api.is_vdo(data_lv.lv_path)

            journal_device, journal_uuid, tags = self.setup_device(
                'journal', self.args.journal, tags, self.args.journal_size)

            tags['ceph.type'] = 'data'
            data_lv.set_tags(tags)

            prepare_filestore(
                data_lv.lv_path,
                journal_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )
        elif self.args.bluestore:
            try:
                vg_name, lv_name = self.args.data.split('/')
                block_lv = api.get_first_lv(filters={'lv_name': lv_name,
                                                 'vg_name': vg_name})
            except ValueError:
                block_lv = None

            if not block_lv:
                block_lv = self.prepare_data_device('block', osd_fsid)

            tags['ceph.block_device'] = block_lv.lv_path
            tags['ceph.block_uuid'] = block_lv.lv_uuid
            tags['ceph.cephx_lockbox_secret'] = cephx_lockbox_secret
            tags['ceph.encrypted'] = encrypted
            tags['ceph.vdo'] = api.is_vdo(block_lv.lv_path)

            wal_device, wal_uuid, tags = self.setup_device(
                'wal', self.args.block_wal, tags, self.args.block_wal_size)
            db_device, db_uuid, tags = self.setup_device(
                'db', self.args.block_db, tags, self.args.block_db_size)

            tags['ceph.type'] = 'block'
            block_lv.set_tags(tags)

            prepare_bluestore(
                block_lv.lv_path,
                wal_device,
                db_device,
                secrets,
                tags,
                self.osd_id,
                osd_fsid,
            )