+import os
import pytest
from copy import deepcopy
from ceph_volume.util import device
disk = device.Device("/dev/sda")
assert disk.is_device is True
+ def test_loop_device_is_not_device(self, fake_call, device_info):
+ data = {"/dev/loop0": {"foo": "bar"}}
+ lsblk = {"TYPE": "loop"}
+ device_info(devices=data, lsblk=lsblk)
+ disk = device.Device("/dev/loop0")
+ assert disk.is_device is False
+
+ def test_loop_device_is_device(self, fake_call, device_info):
+ data = {"/dev/loop0": {"foo": "bar"}}
+ lsblk = {"TYPE": "loop"}
+ os.environ["CEPH_VOLUME_USE_LOOP_DEVICES"] = "1"
+ device_info(devices=data, lsblk=lsblk)
+ disk = device.Device("/dev/loop0")
+ assert disk.is_device is True
+ del os.environ["CEPH_VOLUME_USE_LOOP_DEVICES"]
+
def test_device_is_rotational(self, fake_call, device_info):
data = {"/dev/sda": {"rotational": "1"}}
lsblk = {"TYPE": "device", "NAME": "sda"}
self.disk_api = dev
device_type = dev.get('TYPE', '')
# always check is this is an lvm member
- if device_type in ['part', 'disk']:
+ valid_types = ['part', 'disk']
+ if os.environ.get("CEPH_VOLUME_USE_LOOP_DEVICES", False):
+ valid_types.append('loop')
+ if device_type in valid_types:
self._set_lvm_membership()
out, err, rc = process.call([
'ceph-bluestore-tool', 'show-label',
@property
def device_type(self):
self.load_blkid_api()
- if self.disk_api:
+ if 'type' in self.sys_api:
+ return self.sys_api['type']
+ elif self.disk_api:
return self.disk_api['TYPE']
elif self.blkid_api:
return self.blkid_api['TYPE']
elif self.blkid_api:
api = self.blkid_api
if api:
- return self.device_type in ['disk', 'device', 'mpath']
+ valid_types = ['disk', 'device', 'mpath']
+ if os.environ.get("CEPH_VOLUME_USE_LOOP_DEVICES", False):
+ valid_types.append('loop')
+ return self.device_type in valid_types
return False
@property
"""
if not os.path.exists(dev):
return False
- # use lsblk first, fall back to using stat
- TYPE = lsblk(dev).get('TYPE')
- if TYPE:
- return TYPE in ['disk', 'mpath']
+ if not dev.startswith('/dev/'):
+ return False
+ if dev[len('/dev/'):].startswith('loop'):
+ if os.environ.get("CEPH_VOLUME_USE_LOOP_DEVICES", False) is False:
+ return False
+ logger.info(
+ "Allowing the use of loop devices since "
+ "CEPH_VOLUME_USE_LOOP_DEVICES is set."
+ )
# fallback to stat
return _stat_is_device(os.lstat(dev).st_mode)
- if stat.S_ISBLK(os.lstat(dev)):
- return True
- return False
def is_partition(dev):
raise OSError('lsblk returned failure, stderr: {}'.format(stderr))
return [re.split(r'\s+', line) for line in stdout]
+
+def get_block_devs_sysfs(_sys_block_path='/sys/block', _sys_dev_block_path='/sys/dev/block'):
+ # First, get devices that are _not_ partitions
+ result = list()
+ dev_names = os.listdir(_sys_block_path)
+ for dev in dev_names:
+ name = kname = os.path.join("/dev", dev)
+ type_ = 'disk'
+ if get_file_contents(os.path.join(_sys_block_path, dev, 'removable')) == "1":
+ continue
+ dm_dir_path = os.path.join(_sys_block_path, dev, 'dm')
+ if os.path.isdir(dm_dir_path):
+ type_ = 'lvm'
+ basename = get_file_contents(os.path.join(dm_dir_path, 'name'))
+ name = os.path.join("/dev/mapper", basename)
+ if dev.startswith('loop'):
+ if os.environ.get("CEPH_VOLUME_USE_LOOP_DEVICES", False) is False:
+ continue
+ # Skip loop devices that are not attached
+ if not os.path.exists(os.path.join(_sys_block_path, dev, 'loop')):
+ continue
+ type_ = 'loop'
+ result.append([kname, name, type_])
+ # Next, look for devices that _are_ partitions
+ for item in os.listdir(_sys_dev_block_path):
+ is_part = get_file_contents(os.path.join(_sys_dev_block_path, item, 'partition')) == "1"
+ dev = os.path.basename(os.readlink(os.path.join(_sys_dev_block_path, item)))
+ if not is_part:
+ continue
+ name = kname = os.path.join("/dev", dev)
+ result.append([name, kname, "part"])
+ return sorted(result, key=lambda x: x[0])
+
+
def get_devices(_sys_block_path='/sys/block', device=''):
"""
Captures all available block devices as reported by lsblk.
device_facts = {}
- block_devs = get_block_devs_lsblk(device=device)
+ block_devs = get_block_devs_sysfs(_sys_block_path)
+
+ block_types = ['disk', 'mpath']
+ if os.environ.get("CEPH_VOLUME_USE_LOOP_DEVICES", False) is not False:
+ block_types.append('loop')
for block in block_devs:
devname = os.path.basename(block[0])
diskname = block[1]
- if block[2] not in ['disk', 'mpath']:
+ if block[2] not in block_types:
continue
sysdir = os.path.join(_sys_block_path, devname)
metadata = {}
metadata['human_readable_size'] = human_readable_size(metadata['size'])
metadata['path'] = diskname
metadata['locked'] = is_locked_raw_device(metadata['path'])
+ metadata['type'] = block[2]
device_facts[diskname] = metadata
return device_facts