def create_report(self, lvs): """ Create a report for LVM dev(s) passed. Returns '{}' to denote failure. """ report = {} pvs = api.get_pvs() for lv in lvs: if not api.is_ceph_device(lv): continue osd_id = lv.tags['ceph.osd_id'] report.setdefault(osd_id, []) lv_report = lv.as_dict() lv_report['devices'] = [ pv.name for pv in pvs if pv.lv_uuid == lv.lv_uuid ] if pvs else [] report[osd_id].append(lv_report) phys_devs = self.create_report_non_lv_device(lv) if phys_devs: report[osd_id].append(phys_devs) return report
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_single_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)
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)
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_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.abspath = lv.lv_path self.vg_name = lv.vg_name self.lv_name = lv.name self.ceph_device = lvm.is_ceph_device(lv) 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() out, err, rc = process.call([ 'ceph-bluestore-tool', 'show-label', '--dev', self.path], verbose_on_failure=False) if rc: self.ceph_device = True self.ceph_disk = CephDiskDevice(self)
def create_report(self, lvs, full_report=True, arg_is_vg=False): """ Create a report for LVM dev(s) passed. Returns '{}' to denote failure. """ if not lvs: return {} def create_report_for_nonlv_device(): # bluestore will not have a journal, filestore will not have # a block/wal/db, so we must skip if not present if dev_type == 'data': return device_uuid = lv.tags.get('ceph.%s_uuid' % dev_type) pv = api.get_first_pv(filters={'vg_name': lv.vg_name}) if device_uuid and pv: report[osd_id].append({'tags': {'PARTUUID': device_uuid}, 'type': dev_type, 'path': pv.pv_name}) report = {} lvs = [lvs] if isinstance(lvs, api.Volume) else lvs for lv in lvs: if not api.is_ceph_device(lv): continue osd_id = lv.tags['ceph.osd_id'] report.setdefault(osd_id, []) lv_report = lv.as_dict() dev_type = lv.tags.get('ceph.type', None) if dev_type != 'journal' or (dev_type == 'journal' and full_report): pvs = api.get_pvs(filters={'lv_uuid': lv.lv_uuid}) lv_report['devices'] = [pv.name for pv in pvs] if pvs else [] report[osd_id].append(lv_report) if arg_is_vg or dev_type in ['journal', 'wal']: create_report_for_nonlv_device() return report
def test_is_not_ceph_device(self, dev): assert not api.is_ceph_device(dev)
def test_is_ceph_device(self): lv_tags = "ceph.type=data,ceph.osd_id=0" osd = api.Volume(lv_name='osd/volume', lv_tags=lv_tags) assert api.is_ceph_device(osd)