mirror of
https://github.com/ceph/ceph
synced 2026-08-02 07:03:18 +00:00
Merge pull request #69569 from guits/fix-77486
ceph-volume: skip internal raid mirror LVs in inventory
This commit is contained in:
commit
62ccfb2eb2
@ -313,11 +313,13 @@ class TestDevice(object):
|
||||
assert not disk.available
|
||||
|
||||
@patch("ceph_volume.util.disk.has_bluestore_label", lambda x: False)
|
||||
@patch('ceph_volume.util.device.disk.path_is_block_device', return_value=True)
|
||||
@patch('ceph_volume.util.device.os.path.realpath')
|
||||
@patch('ceph_volume.util.device.os.path.islink')
|
||||
def test_reject_lv_symlink_to_device(self,
|
||||
m_os_path_islink,
|
||||
m_os_path_realpath,
|
||||
m_path_is_block_device,
|
||||
device_info,
|
||||
fake_call):
|
||||
m_os_path_islink.return_value = True
|
||||
@ -327,6 +329,26 @@ class TestDevice(object):
|
||||
device_info(lv=lv,lsblk=lsblk)
|
||||
disk = device.Device("/dev/vg/lv")
|
||||
assert disk.path == '/dev/vg/lv'
|
||||
m_path_is_block_device.assert_called_with('/dev/vg/lv')
|
||||
|
||||
@patch("ceph_volume.util.disk.has_bluestore_label", lambda x: False)
|
||||
@patch('ceph_volume.util.device.disk.path_is_block_device', return_value=False)
|
||||
@patch('ceph_volume.util.device.os.path.realpath')
|
||||
@patch('ceph_volume.util.device.os.path.islink')
|
||||
def test_lv_keeps_mapper_path_when_lv_path_missing(self,
|
||||
m_os_path_islink,
|
||||
m_os_path_realpath,
|
||||
m_path_is_block_device,
|
||||
device_info,
|
||||
fake_call):
|
||||
m_os_path_islink.return_value = False
|
||||
m_os_path_realpath.return_value = '/dev/mapper/vg-var_rmeta_0'
|
||||
lv = {"lv_path": "/dev/vg/var_rmeta_0", "vg_name": "vg", "name": "var_rmeta_0", "tags": {}}
|
||||
lsblk = {"TYPE": "lvm", "NAME": "vg-var_rmeta_0"}
|
||||
device_info(lv=lv, lsblk=lsblk)
|
||||
disk = device.Device("/dev/mapper/vg-var_rmeta_0")
|
||||
assert disk.path == '/dev/mapper/vg-var_rmeta_0'
|
||||
m_path_is_block_device.assert_called_with('/dev/vg/var_rmeta_0')
|
||||
|
||||
@patch("ceph_volume.util.disk.has_bluestore_label", lambda x: False)
|
||||
def test_reject_smaller_than_5gb(self, fake_call, device_info):
|
||||
|
||||
@ -428,8 +428,10 @@ class TestGetDevices(object):
|
||||
fake_filesystem.create_file('/sys/block/dm-0/size', contents='204800')
|
||||
fake_filesystem.create_file('/sys/block/dm-0/queue/rotational', contents='1')
|
||||
fake_filesystem.create_file('/sys/block/dm-0/queue/hw_sector_size', contents='512')
|
||||
fake_filesystem.create_file(lv_path, st_mode=(stat.S_IFBLK | 0o600))
|
||||
with patch("ceph_volume.util.disk.UdevData") as MockUdevData:
|
||||
mock_instance = MagicMock()
|
||||
mock_instance.is_internal_lv = False
|
||||
mock_instance.preferred_block_path = lv_path
|
||||
mock_instance.environment = {}
|
||||
MockUdevData.return_value = mock_instance
|
||||
@ -438,6 +440,46 @@ class TestGetDevices(object):
|
||||
assert result[lv_path]['type'] == 'lvm'
|
||||
assert result[lv_path]['human_readable_size'] == '100.00 MB'
|
||||
|
||||
def test_internal_raid_lv_is_excluded(self, patched_get_block_devs_sysfs, fake_filesystem):
|
||||
mapper_path = '/dev/mapper/debian-var_rmeta_0'
|
||||
dm_path = '/dev/dm-5'
|
||||
patched_get_block_devs_sysfs.return_value = [
|
||||
[dm_path, mapper_path, 'lvm', dm_path]
|
||||
]
|
||||
fake_filesystem.create_dir('/sys/block/dm-5/slaves')
|
||||
fake_filesystem.create_dir('/sys/block/dm-5/queue')
|
||||
fake_filesystem.create_file('/sys/block/dm-5/size', contents='8192')
|
||||
fake_filesystem.create_file('/sys/block/dm-5/queue/rotational', contents='1')
|
||||
fake_filesystem.create_file('/sys/block/dm-5/queue/hw_sector_size', contents='512')
|
||||
with patch("ceph_volume.util.disk.UdevData") as MockUdevData:
|
||||
mock_instance = MagicMock()
|
||||
mock_instance.is_internal_lv = True
|
||||
MockUdevData.return_value = mock_instance
|
||||
result = disk.get_devices()
|
||||
assert mapper_path not in result
|
||||
assert not result
|
||||
|
||||
def test_lvm_device_without_accessible_node_is_excluded(
|
||||
self, patched_get_block_devs_sysfs, fake_filesystem
|
||||
):
|
||||
mapper_path = '/dev/mapper/debian-var_rmeta_0'
|
||||
dm_path = '/dev/dm-5'
|
||||
patched_get_block_devs_sysfs.return_value = [
|
||||
[dm_path, mapper_path, 'lvm', dm_path]
|
||||
]
|
||||
fake_filesystem.create_dir('/sys/block/dm-5/slaves')
|
||||
fake_filesystem.create_dir('/sys/block/dm-5/queue')
|
||||
fake_filesystem.create_file('/sys/block/dm-5/size', contents='8192')
|
||||
fake_filesystem.create_file('/sys/block/dm-5/queue/rotational', contents='1')
|
||||
fake_filesystem.create_file('/sys/block/dm-5/queue/hw_sector_size', contents='512')
|
||||
with patch("ceph_volume.util.disk.UdevData") as MockUdevData:
|
||||
mock_instance = MagicMock()
|
||||
mock_instance.is_internal_lv = False
|
||||
mock_instance.preferred_block_path = '/dev/debian/var_rmeta_0'
|
||||
MockUdevData.return_value = mock_instance
|
||||
result = disk.get_devices()
|
||||
assert not result
|
||||
|
||||
def test_nvme_reads_vendor_model_rev_under_controller(
|
||||
self, patched_get_block_devs_sysfs, fake_filesystem
|
||||
):
|
||||
@ -1047,6 +1089,36 @@ V:1"""
|
||||
def test_dashed_path_with_lvm(self) -> None:
|
||||
assert disk.UdevData(self.fake_device).dashed_path == '/dev/mapper/fake_vg1-fake-lv1'
|
||||
|
||||
@patch('ceph_volume.util.disk.os.stat', _udev_data_patched_os_stat)
|
||||
@patch('ceph_volume.util.disk.os.minor', Mock(return_value=1))
|
||||
@patch('ceph_volume.util.disk.os.major', Mock(return_value=998))
|
||||
def test_is_internal_lv_true_for_raid_metadata(self) -> None:
|
||||
udev = disk.UdevData(self.fake_device)
|
||||
udev.environment['DM_LV_NAME'] = 'var_rmeta_0'
|
||||
assert udev.is_internal_lv
|
||||
|
||||
@patch('ceph_volume.util.disk.os.stat', _udev_data_patched_os_stat)
|
||||
@patch('ceph_volume.util.disk.os.minor', Mock(return_value=1))
|
||||
@patch('ceph_volume.util.disk.os.major', Mock(return_value=998))
|
||||
def test_is_internal_lv_true_for_raid_image(self) -> None:
|
||||
udev = disk.UdevData(self.fake_device)
|
||||
udev.environment['DM_LV_NAME'] = 'var_rimage_1'
|
||||
assert udev.is_internal_lv
|
||||
|
||||
@patch('ceph_volume.util.disk.os.stat', _udev_data_patched_os_stat)
|
||||
@patch('ceph_volume.util.disk.os.minor', Mock(return_value=1))
|
||||
@patch('ceph_volume.util.disk.os.major', Mock(return_value=998))
|
||||
def test_is_internal_lv_true_for_layered_lv(self) -> None:
|
||||
udev = disk.UdevData(self.fake_device)
|
||||
udev.environment['DM_LV_LAYER'] = 'var'
|
||||
assert udev.is_internal_lv
|
||||
|
||||
@patch('ceph_volume.util.disk.os.stat', _udev_data_patched_os_stat)
|
||||
@patch('ceph_volume.util.disk.os.minor', Mock(return_value=1))
|
||||
@patch('ceph_volume.util.disk.os.major', Mock(return_value=998))
|
||||
def test_is_internal_lv_false_for_public_lv(self) -> None:
|
||||
assert not disk.UdevData(self.fake_device).is_internal_lv
|
||||
|
||||
@patch('ceph_volume.util.disk.os.stat', _udev_data_patched_os_stat)
|
||||
@patch('ceph_volume.util.disk.os.minor', Mock(return_value=1))
|
||||
@patch('ceph_volume.util.disk.os.major', Mock(return_value=998))
|
||||
|
||||
@ -236,7 +236,8 @@ class Device(object):
|
||||
if lv:
|
||||
self.lv_api = lv
|
||||
self.lvs = [lv]
|
||||
self.path = lv.lv_path
|
||||
if disk.path_is_block_device(lv.lv_path):
|
||||
self.path = lv.lv_path
|
||||
self.vg_name = lv.vg_name
|
||||
self.lv_name = lv.name
|
||||
self.ceph_device_lvm = lvm.is_ceph_device(lv)
|
||||
@ -319,7 +320,10 @@ class Device(object):
|
||||
src/common/blkdev.cc
|
||||
"""
|
||||
|
||||
udev_data = disk.UdevData(self.path)
|
||||
try:
|
||||
udev_data = disk.UdevData(self.path)
|
||||
except RuntimeError:
|
||||
return ''
|
||||
env = udev_data.environment
|
||||
parts: list[str] = []
|
||||
model = env.get('ID_MODEL', '')
|
||||
|
||||
@ -175,6 +175,14 @@ def _stat_is_device(stat_obj):
|
||||
return stat.S_ISBLK(stat_obj)
|
||||
|
||||
|
||||
def path_is_block_device(path: str) -> bool:
|
||||
"""True if ``path`` exists and is a block device (follows symlinks)."""
|
||||
try:
|
||||
return _stat_is_device(os.stat(path).st_mode)
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def _lsblk_parser(line):
|
||||
"""
|
||||
Parses lines in lsblk output. Requires output to be in pair mode (``-P`` flag). Lines
|
||||
@ -921,7 +929,22 @@ def get_devices(_sys_block_path='/sys/block', device=''):
|
||||
for block in block_devs:
|
||||
metadata: Dict[str, Any] = {}
|
||||
if block[2] == 'lvm':
|
||||
block[1] = UdevData(block[1]).preferred_block_path
|
||||
try:
|
||||
udev_data = UdevData(block[1])
|
||||
except RuntimeError as exc:
|
||||
logger.debug(
|
||||
'get_devices(): skipping LVM device %s: %s', block[1], exc)
|
||||
continue
|
||||
if udev_data.is_internal_lv:
|
||||
logger.debug(
|
||||
'get_devices(): skipping internal LVM LV %s', block[1])
|
||||
continue
|
||||
block[1] = udev_data.preferred_block_path
|
||||
if not path_is_block_device(block[1]):
|
||||
logger.debug(
|
||||
'get_devices(): skipping LVM device without accessible node %s',
|
||||
block[1])
|
||||
continue
|
||||
devname = os.path.basename(block[0])
|
||||
diskname = block[1]
|
||||
if block[2] not in block_types:
|
||||
@ -1546,6 +1569,16 @@ class UdevData:
|
||||
"""
|
||||
return self.environment.get('DM_UUID', '').startswith('LVM')
|
||||
|
||||
@property
|
||||
def is_internal_lv(self) -> bool:
|
||||
lv_name = self.environment.get('DM_LV_NAME', '')
|
||||
if not lv_name:
|
||||
return False
|
||||
for marker in ('_rmeta_', '_rimage_', '_rtmeta_', '_rtimage_'):
|
||||
if marker in lv_name:
|
||||
return True
|
||||
return bool(self.environment.get('DM_LV_LAYER', ''))
|
||||
|
||||
@property
|
||||
def slashed_path(self) -> str:
|
||||
"""Get the LVM path structured with slashes.
|
||||
@ -1575,14 +1608,6 @@ class UdevData:
|
||||
result = f'/dev/mapper/{name}'
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def _path_is_block_device(path: str) -> bool:
|
||||
"""True if ``path`` exists and is a block device (follows symlinks)."""
|
||||
try:
|
||||
return _stat_is_device(os.stat(path).st_mode)
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
@property
|
||||
def preferred_block_path(self) -> str:
|
||||
"""Return a device path that exists for typical open(2) / blkid usage.
|
||||
@ -1598,9 +1623,9 @@ class UdevData:
|
||||
if not self.is_lvm:
|
||||
return self.path
|
||||
slashed: str = self.slashed_path
|
||||
if self._path_is_block_device(slashed):
|
||||
if path_is_block_device(slashed):
|
||||
return slashed
|
||||
dashed: str = self.dashed_path
|
||||
if self._path_is_block_device(dashed):
|
||||
if path_is_block_device(dashed):
|
||||
return dashed
|
||||
return self.path
|
||||
|
||||
Loading…
Reference in New Issue
Block a user