summaryrefslogtreecommitdiffstats
path: root/src/ceph-volume/ceph_volume/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/ceph-volume/ceph_volume/util')
-rw-r--r--src/ceph-volume/ceph_volume/util/arg_validators.py11
-rw-r--r--src/ceph-volume/ceph_volume/util/device.py25
-rw-r--r--src/ceph-volume/ceph_volume/util/disk.py89
-rw-r--r--src/ceph-volume/ceph_volume/util/encryption.py27
4 files changed, 87 insertions, 65 deletions
diff --git a/src/ceph-volume/ceph_volume/util/arg_validators.py b/src/ceph-volume/ceph_volume/util/arg_validators.py
index 1abb5165e..e936cab89 100644
--- a/src/ceph-volume/ceph_volume/util/arg_validators.py
+++ b/src/ceph-volume/ceph_volume/util/arg_validators.py
@@ -4,11 +4,20 @@ import math
from ceph_volume import terminal, decorators, process
from ceph_volume.util.device import Device
from ceph_volume.util import disk
-
+from ceph_volume.util.encryption import set_dmcrypt_no_workqueue
+from ceph_volume import process, conf
def valid_osd_id(val):
return str(int(val))
+class DmcryptAction(argparse._StoreTrueAction):
+ def __init__(self, *args, **kwargs):
+ super(DmcryptAction, self).__init__(*args, **kwargs)
+
+ def __call__(self, *args, **kwargs):
+ set_dmcrypt_no_workqueue()
+ super(DmcryptAction, self).__call__(*args, **kwargs)
+
class ValidDevice(object):
def __init__(self, as_string=False, gpt_ok=False):
diff --git a/src/ceph-volume/ceph_volume/util/device.py b/src/ceph-volume/ceph_volume/util/device.py
index d61222afe..1b52774d1 100644
--- a/src/ceph-volume/ceph_volume/util/device.py
+++ b/src/ceph-volume/ceph_volume/util/device.py
@@ -121,13 +121,8 @@ class Device(object):
# check if we are not a device mapper
if "dm-" not in real_path:
self.path = real_path
- if not sys_info.devices:
- if self.path:
- sys_info.devices = disk.get_devices(device=self.path)
- else:
- sys_info.devices = disk.get_devices()
- if sys_info.devices.get(self.path, {}):
- self.device_nodes = sys_info.devices[self.path]['device_nodes']
+ if not sys_info.devices.get(self.path):
+ sys_info.devices = disk.get_devices()
self.sys_api = sys_info.devices.get(self.path, {})
self.partitions = self._get_partitions()
self.lv_api = None
@@ -143,6 +138,8 @@ class Device(object):
self._is_lvm_member = None
self.ceph_device = False
self._parse()
+ if self.path in sys_info.devices.keys():
+ self.device_nodes = sys_info.devices[self.path]['device_nodes']
self.lsm_data = self.fetch_lsm(with_lsm)
self.available_lvm, self.rejected_reasons_lvm = self._check_lvm_reject_reasons()
@@ -460,11 +457,11 @@ class Device(object):
def device_type(self):
self.load_blkid_api()
if 'type' in self.sys_api:
- return self.sys_api['type']
+ return self.sys_api.get('type')
elif self.disk_api:
- return self.disk_api['TYPE']
+ return self.disk_api.get('TYPE')
elif self.blkid_api:
- return self.blkid_api['TYPE']
+ return self.blkid_api.get('TYPE')
@property
def is_mpath(self):
@@ -478,9 +475,9 @@ class Device(object):
def is_partition(self):
self.load_blkid_api()
if self.disk_api:
- return self.disk_api['TYPE'] == 'part'
+ return self.disk_api.get('TYPE') == 'part'
elif self.blkid_api:
- return self.blkid_api['TYPE'] == 'part'
+ return self.blkid_api.get('TYPE') == 'part'
return False
@property
@@ -594,8 +591,8 @@ class Device(object):
def _check_generic_reject_reasons(self):
reasons = [
- ('removable', 1, 'removable'),
- ('ro', 1, 'read-only'),
+ ('id_bus', 'usb', 'id_bus'),
+ ('ro', '1', 'read-only'),
]
rejected = [reason for (k, v, reason) in reasons if
self.sys_api.get(k, '') == v]
diff --git a/src/ceph-volume/ceph_volume/util/disk.py b/src/ceph-volume/ceph_volume/util/disk.py
index ee061b724..2984c391d 100644
--- a/src/ceph-volume/ceph_volume/util/disk.py
+++ b/src/ceph-volume/ceph_volume/util/disk.py
@@ -6,6 +6,7 @@ import time
from ceph_volume import process
from ceph_volume.api import lvm
from ceph_volume.util.system import get_file_contents
+from typing import Dict, List, Any
logger = logging.getLogger(__name__)
@@ -364,30 +365,18 @@ def is_device(dev):
return TYPE in ['disk', 'mpath']
# fallback to stat
- return _stat_is_device(os.lstat(dev).st_mode)
+ return _stat_is_device(os.lstat(dev).st_mode) and not is_partition(dev)
-def is_partition(dev):
+def is_partition(dev: str) -> bool:
"""
Boolean to determine if a given device is a partition, like /dev/sda1
"""
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 == 'part'
-
- # fallback to stat
- stat_obj = os.stat(dev)
- if _stat_is_device(stat_obj.st_mode):
- return False
- major = os.major(stat_obj.st_rdev)
- minor = os.minor(stat_obj.st_rdev)
- if os.path.exists('/sys/dev/block/%d:%d/partition' % (major, minor)):
- return True
- return False
+ partitions = get_partitions()
+ return dev.split("/")[-1] in partitions
def is_ceph_rbd(dev):
@@ -763,36 +752,34 @@ class AllowLoopDevices(object):
allow_loop_devices = AllowLoopDevices()
-def get_block_devs_sysfs(_sys_block_path='/sys/block', _sys_dev_block_path='/sys/dev/block', device=''):
- def holder_inner_loop():
+def get_block_devs_sysfs(_sys_block_path: str = '/sys/block', _sys_dev_block_path: str = '/sys/dev/block', device: str = '') -> List[List[str]]:
+ def holder_inner_loop() -> bool:
for holder in holders:
# /sys/block/sdy/holders/dm-8/dm/uuid
- holder_dm_type = get_file_contents(os.path.join(_sys_block_path, dev, f'holders/{holder}/dm/uuid')).split('-')[0].lower()
+ holder_dm_type: str = get_file_contents(os.path.join(_sys_block_path, dev, f'holders/{holder}/dm/uuid')).split('-')[0].lower()
if holder_dm_type == 'mpath':
return True
# First, get devices that are _not_ partitions
- result = list()
+ result: List[List[str]] = list()
if not device:
- dev_names = os.listdir(_sys_block_path)
+ dev_names: List[str] = os.listdir(_sys_block_path)
else:
dev_names = [device]
for dev in dev_names:
- name = kname = os.path.join("/dev", dev)
+ name = kname = pname = os.path.join("/dev", dev)
if not os.path.exists(name):
continue
- type_ = 'disk'
- holders = os.listdir(os.path.join(_sys_block_path, dev, 'holders'))
- if get_file_contents(os.path.join(_sys_block_path, dev, 'removable')) == "1":
- continue
+ type_: str = 'disk'
+ holders: List[str] = os.listdir(os.path.join(_sys_block_path, dev, 'holders'))
if holder_inner_loop():
continue
- dm_dir_path = os.path.join(_sys_block_path, dev, 'dm')
+ dm_dir_path: str = os.path.join(_sys_block_path, dev, 'dm')
if os.path.isdir(dm_dir_path):
- dm_type = get_file_contents(os.path.join(dm_dir_path, 'uuid'))
- type_ = dm_type.split('-')[0].lower()
- basename = get_file_contents(os.path.join(dm_dir_path, 'name'))
- name = os.path.join("/dev/mapper", basename)
+ dm_type: str = get_file_contents(os.path.join(dm_dir_path, 'uuid'))
+ type_: List[str] = dm_type.split('-')[0].lower()
+ basename: str = get_file_contents(os.path.join(dm_dir_path, 'name'))
+ name: str = os.path.join("/dev/mapper", basename)
if dev.startswith('loop'):
if not allow_loop_devices():
continue
@@ -800,28 +787,25 @@ def get_block_devs_sysfs(_sys_block_path='/sys/block', _sys_dev_block_path='/sys
if not os.path.exists(os.path.join(_sys_block_path, dev, 'loop')):
continue
type_ = 'loop'
- result.append([kname, name, type_])
+ result.append([kname, name, type_, pname])
# 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"])
+ partitions: Dict[str, str] = get_partitions()
+ for partition in partitions.keys():
+ name = kname = os.path.join("/dev", partition)
+ result.append([name, kname, "part", partitions[partition]])
return sorted(result, key=lambda x: x[0])
-def get_partitions(_sys_dev_block_path ='/sys/dev/block'):
- devices = os.listdir(_sys_dev_block_path)
- result = dict()
+def get_partitions(_sys_dev_block_path ='/sys/dev/block') -> List[str]:
+ devices: List[str] = os.listdir(_sys_dev_block_path)
+ result: Dict[str, str] = dict()
for device in devices:
- device_path = os.path.join(_sys_dev_block_path, device)
- is_partition = get_file_contents(os.path.join(device_path, 'partition')) == "1"
+ device_path: str = os.path.join(_sys_dev_block_path, device)
+ is_partition: bool = int(get_file_contents(os.path.join(device_path, 'partition'), '0')) > 0
if not is_partition:
continue
- partition_sys_name = os.path.basename(os.readlink(device_path))
- parent_device_sys_name = os.readlink(device_path).split('/')[-2:-1][0]
+ partition_sys_name: str = os.path.basename(os.path.realpath(device_path))
+ parent_device_sys_name: str = os.path.realpath(device_path).split('/')[-2:-1][0]
result[partition_sys_name] = parent_device_sys_name
return result
@@ -839,13 +823,13 @@ def get_devices(_sys_block_path='/sys/block', device=''):
device_facts = {}
block_devs = get_block_devs_sysfs(_sys_block_path)
- partitions = get_partitions()
block_types = ['disk', 'mpath', 'lvm', 'part']
if allow_loop_devices():
block_types.append('loop')
for block in block_devs:
+ metadata: Dict[str, Any] = {}
if block[2] == 'lvm':
block[1] = lvm.get_lv_path_from_mapper(block[1])
devname = os.path.basename(block[0])
@@ -854,8 +838,7 @@ def get_devices(_sys_block_path='/sys/block', device=''):
continue
sysdir = os.path.join(_sys_block_path, devname)
if block[2] == 'part':
- sysdir = os.path.join(_sys_block_path, partitions[devname], devname)
- metadata = {}
+ sysdir = os.path.join(_sys_block_path, block[3], devname)
# If the device is ceph rbd it gets excluded
if is_ceph_rbd(diskname):
@@ -890,7 +873,7 @@ def get_devices(_sys_block_path='/sys/block', device=''):
metadata['device_nodes'] = ','.join(device_slaves)
else:
if block[2] == 'part':
- metadata['device_nodes'] = partitions[devname]
+ metadata['device_nodes'] = block[3]
else:
metadata['device_nodes'] = devname
@@ -920,7 +903,13 @@ def get_devices(_sys_block_path='/sys/block', device=''):
metadata['size'] = float(size) * 512
metadata['human_readable_size'] = human_readable_size(metadata['size'])
metadata['path'] = diskname
+ metadata['devname'] = devname
metadata['type'] = block[2]
+ metadata['parent'] = block[3]
+
+ # some facts from udevadm
+ p = udevadm_property(sysdir)
+ metadata['id_bus'] = p.get('ID_BUS', '')
device_facts[diskname] = metadata
return device_facts
diff --git a/src/ceph-volume/ceph_volume/util/encryption.py b/src/ceph-volume/ceph_volume/util/encryption.py
index f8aea80b4..844a81620 100644
--- a/src/ceph-volume/ceph_volume/util/encryption.py
+++ b/src/ceph-volume/ceph_volume/util/encryption.py
@@ -6,10 +6,28 @@ from ceph_volume.util import constants, system
from ceph_volume.util.device import Device
from .prepare import write_keyring
from .disk import lsblk, device_family, get_part_entry_type
+from packaging import version
logger = logging.getLogger(__name__)
mlogger = terminal.MultiLogger(__name__)
+def set_dmcrypt_no_workqueue(target_version: str = '2.3.4') -> None:
+ """
+ set `conf.dmcrypt_no_workqueue` to `True` if the available
+ version of `cryptsetup` is greater or equal to `version`
+ """
+ command = ["cryptsetup", "--version"]
+ out, err, rc = process.call(command)
+ try:
+ if version.parse(out[0]) >= version.parse(f'cryptsetup {target_version}'):
+ conf.dmcrypt_no_workqueue = True
+ except IndexError:
+ mlogger.debug(f'cryptsetup version check: rc={rc} out={out} err={err}')
+ raise RuntimeError("Couldn't check the cryptsetup version.")
+
+def bypass_workqueue(device: str) -> bool:
+ return not Device(device).rotational and conf.dmcrypt_no_workqueue
+
def get_key_size_from_conf():
"""
Return the osd dmcrypt key size from config file.
@@ -79,6 +97,10 @@ def plain_open(key, device, mapping):
'--key-size', '256',
]
+ if bypass_workqueue(device):
+ command.extend(['--perf-no_read_workqueue',
+ '--perf-no_write_workqueue'])
+
process.call(command, stdin=key, terminal_verbose=True, show_command=True)
@@ -103,6 +125,11 @@ def luks_open(key, device, mapping):
device,
mapping,
]
+
+ if bypass_workqueue(device):
+ command.extend(['--perf-no_read_workqueue',
+ '--perf-no_write_workqueue'])
+
process.call(command, stdin=key, terminal_verbose=True, show_command=True)