Beispiel #1
0
    def generate(self, devs=None):
        logger.debug('Listing block devices via lsblk...')

        if devs is None or devs == []:
            devs = []
            # If no devs are given initially, we want to list ALL devices including children and
            # parents. Parent disks with child partitions may be the appropriate device to return if
            # the parent disk has a bluestore header, but children may be the most appropriate
            # devices to return if the parent disk does not have a bluestore header.
            out, err, ret = process.call([
                'lsblk',
                '--paths',
                '--output=NAME',
                '--noheadings',
            ])
            assert not ret
            devs = out

        result = {}
        logger.debug('inspecting devices: {}'.format(devs))
        for dev in devs:
            info = disk.lsblk(dev, abspath=True)
            # Linux kernels built with CONFIG_ATARI_PARTITION enabled can falsely interpret
            # bluestore's on-disk format as an Atari partition table. These false Atari partitions
            # can be interpreted as real OSDs if a bluestore OSD was previously created on the false
            # partition. See https://tracker.ceph.com/issues/52060 for more info. If a device has a
            # parent, it is a child. If the parent is a valid bluestore OSD, the child will only
            # exist if it is a phantom Atari partition, and the child should be ignored. If the
            # parent isn't bluestore, then the child could be a valid bluestore OSD. If we fail to
            # determine whether a parent is bluestore, we should err on the side of not reporting
            # the child so as not to give a false negative.
            if 'PKNAME' in info and info['PKNAME'] != "":
                parent = info['PKNAME']
                try:
                    if disk.has_bluestore_label(parent):
                        logger.warning((
                            'ignoring child device {} whose parent {} is a BlueStore OSD.'
                            .format(dev, parent),
                            'device is likely a phantom Atari partition. device info: {}'
                            .format(info)))
                        continue
                except OSError as e:
                    logger.error((
                        'ignoring child device {} to avoid reporting invalid BlueStore data from phantom Atari partitions.'
                        .format(dev),
                        'failed to determine if parent device {} is BlueStore. err: {}'
                        .format(parent, e)))
                    continue

            bs_info = _get_bluestore_info(dev)
            if bs_info is None:
                # None is also returned in the rare event that there is an issue reading info from
                # a BlueStore disk, so be sure to log our assumption that it isn't bluestore
                logger.info(
                    'device {} does not have BlueStore information'.format(
                        dev))
                continue
            result[bs_info['osd_uuid']] = bs_info

        return result
Beispiel #2
0
    def _parse(self):
        lv = None
        if not self.sys_api:
            # if no device was found check if we are a partition
            partname = self.path.split('/')[-1]
            for device, info in sys_info.devices.items():
                part = info['partitions'].get(partname, {})
                if part:
                    self.sys_api = part
                    break

        if self.lvs:
            for _lv in self.lvs:
                # if the path is not absolute, we have 'vg/lv', let's use LV name
                # to get the LV.
                if self.path[0] == '/':
                    if _lv.lv_path == self.path:
                        lv = _lv
                        break
                else:
                    vgname, lvname = self.path.split('/')
                    if _lv.lv_name == lvname and _lv.vg_name == vgname:
                        lv = _lv
                        break
        else:
            if self.path[0] == '/':
                lv = lvm.get_single_lv(filters={'lv_path': self.path})
            else:
                vgname, lvname = self.path.split('/')
                lv = lvm.get_single_lv(filters={
                    'lv_name': lvname,
                    'vg_name': vgname
                })

        if lv:
            self.lv_api = lv
            self.lvs = [lv]
            self.path = lv.lv_path
            self.vg_name = lv.vg_name
            self.lv_name = lv.name
            self.ceph_device = lvm.is_ceph_device(lv)
        else:
            if self.lsblk_all:
                for dev in self.lsblk_all:
                    if dev['NAME'] == os.path.basename(self.path):
                        break
            else:
                dev = disk.lsblk(self.path)
            self.disk_api = dev
            device_type = dev.get('TYPE', '')
            # always check is this is an lvm member
            valid_types = ['part', 'disk']
            if allow_loop_devices():
                valid_types.append('loop')
            if device_type in valid_types:
                self._set_lvm_membership()
            self.ceph_device = disk.has_bluestore_label(self.path)

        self.ceph_disk = CephDiskDevice(self)
Beispiel #3
0
 def _is_valid_device(self, raise_sys_exit=True):
     super()._is_valid_device()
     if self._device.used_by_ceph:
         terminal.info('Device {} is already prepared'.format(
             self.dev_path))
         if raise_sys_exit:
             raise SystemExit(0)
     if self._device.has_fs and not self._device.used_by_ceph:
         raise RuntimeError("Device {} has a filesystem.".format(
             self.dev_path))
     if self.dev_path[0] == '/' and disk.has_bluestore_label(self.dev_path):
         raise RuntimeError("Device {} has bluestore signature.".format(
             self.dev_path))
     return self._device
Beispiel #4
0
    def _check_generic_reject_reasons(self):
        reasons = [
            ('removable', 1, 'removable'),
            ('ro', 1, 'read-only'),
            ('locked', 1, 'locked'),
        ]
        rejected = [
            reason for (k, v, reason) in reasons
            if self.sys_api.get(k, '') == v
        ]
        if self.is_acceptable_device:
            # reject disks smaller than 5GB
            if int(self.sys_api.get('size', 0)) < 5368709120:
                rejected.append('Insufficient space (<5GB)')
        else:
            rejected.append(
                "Device type is not acceptable. It should be raw device or partition"
            )
        if self.is_ceph_disk_member:
            rejected.append("Used by ceph-disk")

        try:
            if self.has_bluestore_label:
                rejected.append('Has BlueStore device label')
        except OSError as e:
            # likely failed to open the device. assuming it is BlueStore is the safest option
            # so that a possibly-already-existing OSD doesn't get overwritten
            logger.error(
                'failed to determine if device {} is BlueStore. device should not be used to avoid false negatives. err: {}'
                .format(self.abspath, e))
            rejected.append('Failed to determine if device is BlueStore')

        if self.is_partition:
            try:
                if disk.has_bluestore_label(self.parent_device):
                    rejected.append('Parent has BlueStore device label')
            except OSError as e:
                # likely failed to open the device. assuming the parent is BlueStore is the safest
                # option so that a possibly-already-existing OSD doesn't get overwritten
                logger.error(
                    'failed to determine if partition {} (parent: {}) has a BlueStore parent. partition should not be used to avoid false negatives. err: {}'
                    .format(self.abspath, self.parent_device, e))
                rejected.append(
                    'Failed to determine if parent device is BlueStore')

        if self.has_gpt_headers:
            rejected.append('Has GPT headers')
        if self.has_partitions:
            rejected.append('Has partitions')
        return rejected
Beispiel #5
0
 def test_device_path_is_a_path(self, fake_filesystem):
     device_path = '/var/lib/ceph/osd/ceph-0'
     fake_filesystem.create_dir(device_path)
     assert not disk.has_bluestore_label(device_path)
Beispiel #6
0
 def has_bluestore_label(self):
     return disk.has_bluestore_label(self.abspath)