From: Kotresh HR Date: Sun, 21 Jun 2026 17:48:15 +0000 (+0530) Subject: mgr/mirroring: handle missing cephfs_mirror object in metrics status X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a7325bafb9ab29f17f45e4c14db56a86632d0ff1;p=ceph.git mgr/mirroring: handle missing cephfs_mirror object in metrics status When snapshot mirroring is not enabled for a filesystem, the cephfs_mirror RADOS object does not exist and "ceph fs snapshot mirror status" fails reading sync stat omap. Map rados ENOENT to a clear MirrorException so the CLI reports that snapshot mirroring must be enabled instead of a generic omap read failure or an uncaught exception. Also catch unexpected errors in metrics_status like other mirror CLI handlers, so the mgr module does not crash on failure. Return -errno.EINVAL from the generic error path instead of the exception message as exit code. Fixes: https://tracker.ceph.com/issues/76686 Signed-off-by: Kotresh HR --- diff --git a/src/pybind/mgr/mirroring/fs/metrics/load.py b/src/pybind/mgr/mirroring/fs/metrics/load.py index 8b2ae3641ae..3b7a275f5ce 100644 --- a/src/pybind/mgr/mirroring/fs/metrics/load.py +++ b/src/pybind/mgr/mirroring/fs/metrics/load.py @@ -24,6 +24,20 @@ from .format import ( log = logging.getLogger(__name__) +MIRROR_OBJECT_NOT_FOUND_MSG = ( + 'cephfs_mirror object not found; enable snapshot mirroring with ' + '"ceph fs snapshot mirror enable "') + + +def _raise_on_sync_stat_read_error(err): + if isinstance(err, rados.Error) and err.errno == errno.ENOENT: + raise MirrorException(-errno.ENOENT, MIRROR_OBJECT_NOT_FOUND_MSG) + if isinstance(err, rados.Error): + log.error(f'failed to read sync stat omap: {err}') + err_no = err.errno if err.errno is not None else errno.EINVAL + raise MirrorException(-err_no, 'failed to read sync stat omap') + raise err + def load_sync_stat_by_keys(ioctx, keys): stats: Dict[str, Any] = {} @@ -43,8 +57,7 @@ def load_sync_stat_by_keys(ioctx, keys): except (json.JSONDecodeError, UnicodeDecodeError) as e: log.warning(f'failed to decode sync stat for key {key}: {e}') except rados.Error as e: - log.error(f'failed to read sync stat omap keys: {e}') - raise MirrorException(-e.errno, 'failed to read sync stat omap keys') + _raise_on_sync_stat_read_error(e) return stats @@ -113,8 +126,7 @@ def load_sync_stat_metrics(ioctx, filesystem, peer_uuid=None, policy=None, stat, policy, dir_path, live_instance_ids)) start = omap_vals.popitem()[0] except rados.Error as e: - log.error(f'failed to read sync stat omap: {e}') - raise MirrorException(-e.errno, 'failed to read sync stat omap') + _raise_on_sync_stat_read_error(e) if policy is not None and peers: with policy.lock: dir_paths = list(policy.dir_states.keys()) diff --git a/src/pybind/mgr/mirroring/fs/snapshot_mirror.py b/src/pybind/mgr/mirroring/fs/snapshot_mirror.py index ec7e838af52..dc7f45c32c2 100644 --- a/src/pybind/mgr/mirroring/fs/snapshot_mirror.py +++ b/src/pybind/mgr/mirroring/fs/snapshot_mirror.py @@ -900,6 +900,9 @@ class FSSnapshotMirror: return 0, json.dumps({'metrics': metrics}, indent=4), '' except MirrorException as me: return me.args[0], '', me.args[1] + except Exception as e: + log.error(f'failed to get snapshot mirror metrics: {e}') + return -errno.EINVAL, '', 'failed to get snapshot mirror metrics' def daemon_status(self, format='json'): try: