コード例 #1
0
ファイル: listing.py プロジェクト: pKhantiviriya/ceph
    def single_report(self, device):
        """
        Generate a report for a single device. This can be either a logical
        volume in the form of vg/lv or a device with an absolute path like
        /dev/sda1 or /dev/sda. Returns '{}' to denote failure.
        """
        lv = api.get_first_lv(filters={'lv_path': device})
        # whether the dev to reported is lv...
        arg_is_vg = False

        # The `device` argument can be a logical volume name or a device path.
        # If it's a path that exists, use the canonical path (in particular,
        # dereference symlinks); otherwise, assume it's a logical volume name
        # and use it as-is.
        if os.path.exists(device):
            device = os.path.realpath(device)

        lv = api.get_first_lv(filters={'lv_path': device})
        if not lv:
            # if device at given path is not LV, it might be PV...
            pv = api.get_first_pv(filters={'pv_name': device})
            if pv:
                lv = api.get_first_lv(filters={'vg_name': pv.vg_name})
            # or VG.
            else:
                vg_name = os.path.dirname(device)
                lv = api.get_first_lv(filters={'vg_name': vg_name})
                arg_is_vg = True

        if not lv:
            return {}

        return self.create_report(lv, full_report=False, arg_is_vg=arg_is_vg)
コード例 #2
0
    def safe_prepare(self, args=None):
        """
        An intermediate step between `main()` and `prepare()` so that we can
        capture the `self.osd_id` in case we need to rollback

        :param args: Injected args, usually from `lvm create` which compounds
                     both `prepare` and `create`
        """
        if args is not None:
            self.args = args

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

        if api.is_ceph_device(lv):
            logger.info("device {} is already used".format(self.args.data))
            raise RuntimeError("skipping {}, it is already prepared".format(self.args.data))
        try:
            self.prepare()
        except Exception:
            logger.exception('lvm prepare was unable to complete')
            logger.info('will rollback OSD ID creation')
            rollback_osd(self.args, self.osd_id)
            raise
        terminal.success("ceph-volume lvm prepare successful for: %s" % self.args.data)
コード例 #3
0
ファイル: zap.py プロジェクト: zwj262310/ceph
    def zap_lv(self, device):
        """
        Device examples: vg-name/lv-name, /dev/vg-name/lv-name
        Requirements: Must be a logical volume (LV)
        """
        lv = api.get_first_lv(filters={
            'lv_name': device.lv_name,
            'vg_name': device.vg_name
        })
        self.unmount_lv(lv)

        wipefs(device.abspath)
        zap_data(device.abspath)

        if self.args.destroy:
            lvs = api.get_lvs(filters={'vg_name': device.vg_name})
            if lvs == []:
                mlogger.info('No LVs left, exiting', device.vg_name)
                return
            elif len(lvs) <= 1:
                mlogger.info(
                    'Only 1 LV left in VG, will proceed to destroy '
                    'volume group %s', device.vg_name)
                api.remove_vg(device.vg_name)
            else:
                mlogger.info('More than 1 LV left in VG, will proceed to '
                             'destroy LV only')
                mlogger.info('Removing LV because --destroy was given: %s',
                             device.abspath)
                api.remove_lv(device.abspath)
        elif lv:
            # just remove all lvm metadata, leaving the LV around
            lv.clear_tags()
コード例 #4
0
ファイル: scan.py プロジェクト: doitroot/ceph_source
    def scan_device(self, path):
        device_metadata = {'path': None, 'uuid': None}
        if not path:
            return device_metadata
        if self.is_encrypted:
            encryption_metadata = encryption.legacy_encrypted(path)
            device_metadata['path'] = encryption_metadata['device']
            device_metadata['uuid'] = disk.get_partuuid(
                encryption_metadata['device'])
            return device_metadata
        # cannot read the symlink if this is tmpfs
        if os.path.islink(path):
            device = os.readlink(path)
        else:
            device = path
        lvm_device = lvm.get_first_lv(filters={'lv_path': device})
        if lvm_device:
            device_uuid = lvm_device.lv_uuid
        else:
            device_uuid = disk.get_partuuid(device)

        device_metadata['uuid'] = device_uuid
        device_metadata['path'] = device

        return device_metadata
コード例 #5
0
ファイル: test_lvm.py プロジェクト: blockspacer/ceph-1
    def test_get_first_lv_single_lv(self, monkeypatch):
        stdout = ['ceph.type=data;/dev/vg/lv;lv;vg']
        monkeypatch.setattr(api.process, 'call', lambda x,**kw: (stdout, '', 0))
        lv = api.Volume(lv_tags='ceph.type=data',
                           lv_path='/dev/vg/lv',
                           lv_name='lv', vg_name='vg')

        lv_ = api.get_first_lv()
        assert isinstance(lv_, api.Volume)
        assert lv_.lv_name == lv.lv_name
コード例 #6
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
コード例 #7
0
    def _parse(self):
        if not sys_info.devices:
            sys_info.devices = disk.get_devices()
        self.sys_api = sys_info.devices.get(self.abspath, {})
        if not self.sys_api:
            # if no device was found check if we are a partition
            partname = self.abspath.split('/')[-1]
            for device, info in sys_info.devices.items():
                part = info['partitions'].get(partname, {})
                if part:
                    self.sys_api = part
                    break

        # if the path is not absolute, we have 'vg/lv', let's use LV name
        # to get the LV.
        if self.path[0] == '/':
            lv = lvm.get_first_lv(filters={'lv_path': self.path})
        else:
            vgname, lvname = self.path.split('/')
            lv = lvm.get_first_lv(filters={
                'lv_name': lvname,
                'vg_name': vgname
            })
        if lv:
            self.lv_api = lv
            self.lvs = [lv]
            self.abspath = lv.lv_path
            self.vg_name = lv.vg_name
            self.lv_name = lv.name
        else:
            dev = disk.lsblk(self.path)
            self.blkid_api = disk.blkid(self.path)
            self.disk_api = dev
            device_type = dev.get('TYPE', '')
            # always check is this is an lvm member
            if device_type in ['part', 'disk']:
                self._set_lvm_membership()

        self.ceph_disk = CephDiskDevice(self)
コード例 #8
0
ファイル: test_lvm.py プロジェクト: blockspacer/ceph-1
    def test_get_first_lv(self, monkeypatch):
        lv1 = api.Volume(lv_tags='ceph.type=data', lv_path='/dev/vg1/lv1',
                         lv_name='lv1', vg_name='vg1')
        lv2 = api.Volume(lv_tags='ceph.type=data', lv_path='/dev/vg2/lv2',
                         lv_name='lv2', vg_name='vg2')
        stdout = ['{};{};{};{}'.format(lv1.lv_tags, lv1.lv_path, lv1.lv_name,
                                       lv1.vg_name),
                  '{};{};{};{}'.format(lv2.lv_tags, lv2.lv_path, lv2.lv_name,
                                       lv2.vg_name)]
        monkeypatch.setattr(api.process, 'call', lambda x,**kw: (stdout, '', 0))

        lv_ = api.get_first_lv()
        assert isinstance(lv_, api.Volume)
        assert lv_.lv_name == lv1.lv_name
コード例 #9
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_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.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_first_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_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,
                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,
            )
コード例 #10
0
ファイル: prepare.py プロジェクト: doitroot/ceph_source
    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,
            )