コード例 #1
0
    def prepare_device(self, arg, device_type, cluster_fsid, osd_fsid):
        """
        Check if ``arg`` is a device or partition to create an LV out of it
        with a distinct volume group name, assigning LV tags on it and
        ultimately, returning the logical volume object.  Failing to detect
        a device or partition will result in error.

        :param arg: The value of ``--data`` when parsing args
        :param device_type: Usually, either ``data`` or ``block`` (filestore vs. bluestore)
        :param cluster_fsid: The cluster fsid/uuid
        :param osd_fsid: The OSD fsid/uuid
        """
        if disk.is_partition(arg) or disk.is_device(arg):
            # we must create a vg, and then a single lv
            vg_name = "ceph-%s" % cluster_fsid
            if api.get_vg(vg_name=vg_name):
                # means we already have a group for this, make a different one
                # XXX this could end up being annoying for an operator, maybe?
                vg_name = "ceph-%s" % str(uuid.uuid4())
            api.create_vg(vg_name, arg)
            lv_name = "osd-%s-%s" % (device_type, osd_fsid)
            return api.create_lv(
                lv_name,
                vg_name,  # the volume group
                tags={'ceph.type': device_type})
        else:
            error = [
                'Cannot use device (%s).' % arg,
                'A vg/lv path or an existing device is needed'
            ]
            raise RuntimeError(' '.join(error))

        raise RuntimeError('no data logical volume found with: %s' % arg)
コード例 #2
0
ファイル: prepare.py プロジェクト: mkoderer/ceph
    def prepare_device(self, arg, device_type, cluster_fsid, osd_fsid):
        """
        Check if ``arg`` is a device or partition to create an LV out of it
        with a distinct volume group name, assigning LV tags on it and
        ultimately, returning the logical volume object.  Failing to detect
        a device or partition will result in error.

        :param arg: The value of ``--data`` when parsing args
        :param device_type: Usually, either ``data`` or ``block`` (filestore vs. bluestore)
        :param cluster_fsid: The cluster fsid/uuid
        :param osd_fsid: The OSD fsid/uuid
        """
        if disk.is_partition(arg) or disk.is_device(arg):
            # we must create a vg, and then a single lv
            vg_name = "ceph-%s" % cluster_fsid
            if api.get_vg(vg_name=vg_name):
                # means we already have a group for this, make a different one
                # XXX this could end up being annoying for an operator, maybe?
                vg_name = "ceph-%s" % str(uuid.uuid4())
            api.create_vg(vg_name, arg)
            lv_name = "osd-%s-%s" % (device_type, osd_fsid)
            return api.create_lv(
                lv_name,
                vg_name,  # the volume group
                tags={'ceph.type': device_type})
        else:
            error = [
                'Cannot use device (%s).' % arg,
                'A vg/lv path or an existing device is needed']
            raise RuntimeError(' '.join(error))

        raise RuntimeError('no data logical volume found with: %s' % arg)
コード例 #3
0
    def prepare_data_device(self, device_type, osd_uuid):
        """
        Check if ``arg`` is a device or partition to create an LV out of it
        with a distinct volume group name, assigning LV tags on it and
        ultimately, returning the logical volume object.  Failing to detect
        a device or partition will result in error.

        :param arg: The value of ``--data`` when parsing args
        :param device_type: Usually, either ``data`` or ``block`` (filestore vs. bluestore)
        :param osd_uuid: The OSD uuid
        """
        device = self.args.data
        if disk.is_partition(device) or disk.is_device(device):
            # we must create a vg, and then a single lv
            lv_name_prefix = "osd-{}".format(device_type)
            kwargs = {
                'device': device,
                'tags': {
                    'ceph.type': device_type
                },
                'slots': self.args.data_slots,
            }
            logger.debug('data device size: {}'.format(self.args.data_size))
            if self.args.data_size != 0:
                kwargs['size'] = self.args.data_size
            return api.create_lv(lv_name_prefix, osd_uuid, **kwargs)
        else:
            error = [
                'Cannot use device ({}).'.format(device),
                'A vg/lv path or an existing device is needed'
            ]
            raise RuntimeError(' '.join(error))

        raise RuntimeError(
            'no data logical volume found with: {}'.format(device))
コード例 #4
0
    def __call__(self, string):
        if not os.path.exists(string):
            error = "Path does not exist: %s" % string
            raise argparse.ArgumentError(None, error)

        arg_is_partition = disk.is_partition(string)
        if arg_is_partition:
            return os.path.abspath(string)
        absolute_path = os.path.abspath(string)
        if not os.path.isdir(absolute_path):
            error = "Argument is not a directory or device which is required to scan"
            raise argparse.ArgumentError(None, error)
        key_files = ['ceph_fsid', 'fsid', 'keyring', 'ready', 'type', 'whoami']
        dir_files = os.listdir(absolute_path)
        for key_file in key_files:
            if key_file not in dir_files:
                terminal.error('All following files must exist in path: %s' %
                               ' '.join(key_files))
                error = "Required file (%s) was not found in OSD dir path: %s" % (
                    key_file, absolute_path)
                raise argparse.ArgumentError(None, error)

        return os.path.abspath(string)
コード例 #5
0
ファイル: arg_validators.py プロジェクト: IlsooByun/ceph
    def __call__(self, string):
        if not os.path.exists(string):
            error = "Path does not exist: %s" % string
            raise argparse.ArgumentError(None, error)

        arg_is_partition = disk.is_partition(string)
        if arg_is_partition:
            return os.path.abspath(string)
        absolute_path = os.path.abspath(string)
        if not os.path.isdir(absolute_path):
            error = "Argument is not a directory or device which is required to scan"
            raise argparse.ArgumentError(None, error)
        key_files = ['ceph_fsid', 'fsid', 'keyring', 'ready', 'type', 'whoami']
        dir_files = os.listdir(absolute_path)
        for key_file in key_files:
            if key_file not in dir_files:
                terminal.error('All following files must exist in path: %s' % ' '.join(key_files))
                error = "Required file (%s) was not found in OSD dir path: %s" % (
                    key_file,
                    absolute_path
                )
                raise argparse.ArgumentError(None, error)

        return os.path.abspath(string)
コード例 #6
0
ファイル: scan.py プロジェクト: Abhishekvrshny/ceph
    def main(self):
        sub_command_help = dedent("""
        Scan an OSD directory (or data device) for files and configurations
        that will allow to take over the management of the OSD.

        Scanned OSDs will get their configurations stored in
        /etc/ceph/osd/<id>-<fsid>.json

        For an OSD ID of 0 with fsid of ``a9d50838-e823-43d6-b01f-2f8d0a77afc2``
        that could mean a scan command that looks like::

            ceph-volume lvm scan /var/lib/ceph/osd/ceph-0

        Which would store the metadata in a JSON file at::

            /etc/ceph/osd/0-a9d50838-e823-43d6-b01f-2f8d0a77afc2.json

        To a scan an existing, running, OSD:

            ceph-volume simple scan /var/lib/ceph/osd/{cluster}-{osd id}

        And to scan a device (mounted or unmounted) that has OSD data in it, for example /dev/sda1

            ceph-volume simple scan /dev/sda1
        """)
        parser = argparse.ArgumentParser(
            prog='ceph-volume simple scan',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description=sub_command_help,
        )

        parser.add_argument(
            '-f', '--force',
            action='store_true',
            help='If OSD has already been scanned, the JSON file will be overwritten'
        )

        parser.add_argument(
            '--stdout',
            action='store_true',
            help='Do not save to a file, output metadata to stdout'
        )

        parser.add_argument(
            'osd_path',
            metavar='OSD_PATH',
            type=arg_validators.OSDPath(),
            nargs='?',
            help='Path to an existing OSD directory or OSD data partition'
        )

        if len(self.argv) == 0:
            print(sub_command_help)
            return

        args = parser.parse_args(self.argv)
        if disk.is_partition(args.osd_path):
            label = disk.lsblk(args.osd_path)['PARTLABEL']
            if 'data' not in label:
                raise RuntimeError('Device must be the data partition, but got: %s' % label)

        # Capture some environment status, so that it can be reused all over
        self.device_mounts = system.get_mounts(devices=True)
        self.path_mounts = system.get_mounts(paths=True)
        self.encryption_metadata = encryption.legacy_encrypted(args.osd_path)
        self.is_encrypted = self.encryption_metadata['encrypted']

        self.scan(args)
コード例 #7
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()}

        cluster_fsid = conf.ceph.get('global', 'fsid')
        osd_fsid = args.osd_fsid or system.generate_uuid()
        # allow re-using an id, in case a prepare failed
        osd_id = args.osd_id or prepare_utils.create_id(
            osd_fsid, json.dumps(secrets))
        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:
                raise RuntimeError('no data logical volume found with: %s' %
                                   args.data)

            tags = {
                'ceph.osd_fsid': osd_fsid,
                'ceph.osd_id': osd_id,
                'ceph.cluster_fsid': cluster_fsid,
                'ceph.cluster_name': conf.cluster,
                'ceph.data_device': data_lv.lv_path,
                'ceph.data_uuid': data_lv.lv_uuid,
            }

            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,
                id_=osd_id,
                fsid=osd_fsid,
            )
        elif args.bluestore:
            block_lv = self.get_lv(args.data)
            if not block_lv:
                if disk.is_partition(args.data) or disk.is_device(args.data):
                    # we must create a vg, and then a single lv
                    vg_name = "ceph-%s" % cluster_fsid
                    if api.get_vg(vg_name=vg_name):
                        # means we already have a group for this, make a different one
                        # XXX this could end up being annoying for an operator, maybe?
                        vg_name = "ceph-%s" % str(uuid.uuid4())
                    api.create_vg(vg_name, args.data)
                    block_name = "osd-block-%s" % osd_fsid
                    block_lv = api.create_lv(
                        block_name,
                        vg_name,  # the volume group
                        tags={'ceph.type': 'block'})
                else:
                    error = [
                        'Cannot use device (%s) for bluestore. ' % args.data,
                        'A vg/lv path or an existing device is needed'
                    ]
                    raise RuntimeError(' '.join(error))

            tags = {
                'ceph.osd_fsid': osd_fsid,
                'ceph.osd_id': osd_id,
                'ceph.cluster_fsid': cluster_fsid,
                'ceph.cluster_name': conf.cluster,
                'ceph.block_device': block_lv.lv_path,
                'ceph.block_uuid': block_lv.lv_uuid,
            }

            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,
                id_=osd_id,
                fsid=osd_fsid,
            )
コード例 #8
0
    def main(self):
        sub_command_help = dedent("""
        Scan an OSD directory (or data device) for files and configurations
        that will allow to take over the management of the OSD.

        Scanned OSDs will get their configurations stored in
        /etc/ceph/osd/<id>-<fsid>.json

        For an OSD ID of 0 with fsid of ``a9d50838-e823-43d6-b01f-2f8d0a77afc2``
        that could mean a scan command that looks like::

            ceph-volume lvm scan /var/lib/ceph/osd/ceph-0

        Which would store the metadata in a JSON file at::

            /etc/ceph/osd/0-a9d50838-e823-43d6-b01f-2f8d0a77afc2.json

        To a scan an existing, running, OSD:

            ceph-volume simple scan /var/lib/ceph/osd/{cluster}-{osd id}

        And to scan a device (mounted or unmounted) that has OSD data in it, for example /dev/sda1

            ceph-volume simple scan /dev/sda1
        """)
        parser = argparse.ArgumentParser(
            prog='ceph-volume simple scan',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description=sub_command_help,
        )

        parser.add_argument(
            '-f',
            '--force',
            action='store_true',
            help=
            'If OSD has already been scanned, the JSON file will be overwritten'
        )

        parser.add_argument(
            '--stdout',
            action='store_true',
            help='Do not save to a file, output metadata to stdout')

        parser.add_argument(
            'osd_path',
            metavar='OSD_PATH',
            type=arg_validators.OSDPath(),
            nargs='?',
            help='Path to an existing OSD directory or OSD data partition')

        if len(self.argv) == 0:
            print(sub_command_help)
            return

        args = parser.parse_args(self.argv)
        if disk.is_partition(args.osd_path):
            label = disk.lsblk(args.osd_path)['PARTLABEL']
            if 'data' not in label:
                raise RuntimeError(
                    'Device must be the data partition, but got: %s' % label)

        # Capture some environment status, so that it can be reused all over
        self.device_mounts = system.get_mounts(devices=True)
        self.path_mounts = system.get_mounts(paths=True)
        self.encryption_metadata = encryption.legacy_encrypted(args.osd_path)
        self.is_encrypted = self.encryption_metadata['encrypted']

        self.scan(args)