Merge pull request #69143 from guits/fix-cv-vg-lv-batch

ceph-volume: retry lvs after empty result and "devices file is missing" stderr
This commit is contained in:
Guillaume Abrioux 2026-06-01 09:57:17 +02:00 committed by GitHub
commit 12c63f2ab5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 0 deletions

View File

@ -70,6 +70,18 @@ def make_filters_lvmcmd_ready(filters: Dict[str, Any], tags: Dict[str, Any]) ->
return ''
def should_retry_lvs_without_devices_file(stdout: List[str],
stderr: List[str],
returncode: int) -> bool:
"""
Detect an LVM 'devices file' mismatch scenario where `lvs` can return no data
and only emits warnings on stderr.
"""
if returncode != 0 or stdout:
return False
return any('devices file is missing' in line.lower() for line in stderr)
def _output_parser(output: List[str], fields: str) -> List[Dict[str, Any]]:
"""
Newer versions of LVM allow ``--reportformat=json``, but older versions,
@ -1177,6 +1189,21 @@ def get_lvs(fields: str = LV_FIELDS, filters: Optional[Dict[str, Any]] = None, t
args = ['lvs'] + LV_CMD_OPTIONS + ['-S', filters_str, '-o', fields]
stdout, stderr, returncode = process.call(args, run_on_host=True, verbose_on_failure=False)
if should_retry_lvs_without_devices_file(stdout, stderr, returncode):
logger.warning(
'lvs returned no output with devices-file warnings; retrying with use_devicesfile=0'
)
retry_args = ['lvs'] + LV_CMD_OPTIONS + [
'--config',
'devices { use_devicesfile=0 }',
'-S',
filters_str,
'-o',
fields,
]
stdout, stderr, returncode = process.call(
retry_args, run_on_host=True, verbose_on_failure=False
)
lvs_report = _output_parser(stdout, fields)
return [Volume(**lv_report) for lv_report in lvs_report]

View File

@ -837,6 +837,31 @@ class TestGetLVs(object):
monkeypatch.setattr(api.process, 'call', lambda x,**kw: ('', '', 0))
assert api.get_lvs() == []
def test_get_lvs_retries_without_devices_file_on_warning(self, monkeypatch):
retry_stdout = ['ceph.type=data;/dev/vg/lv;lv;vg;lv-uuid;1024']
calls = []
def fake_call(cmd, **kw):
calls.append(cmd)
if len(calls) == 1:
return (
[],
['WARNING: devices file is missing /dev/mapper/eui.foo using multipath component /dev/nvme0n1.'],
0,
)
return (retry_stdout, [], 0)
monkeypatch.setattr(api.process, 'call', fake_call)
lvs_ = api.get_lvs()
assert len(calls) == 2
assert '--config' in calls[1]
assert 'devices { use_devicesfile=0 }' in calls[1]
assert len(lvs_) == 1
assert lvs_[0].lv_name == 'lv'
assert lvs_[0].vg_name == 'vg'
class TestGetSinglePV(object):