]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/mirroring: handle missing cephfs_mirror object in metrics status
authorKotresh HR <khiremat@redhat.com>
Sun, 21 Jun 2026 17:48:15 +0000 (23:18 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 23 Jun 2026 15:19:29 +0000 (20:49 +0530)
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 <khiremat@redhat.com>
src/pybind/mgr/mirroring/fs/metrics/load.py
src/pybind/mgr/mirroring/fs/snapshot_mirror.py

index 8b2ae3641aeb813e329141818fbde2c8dfe3ac16..3b7a275f5ceefa4ee5627c1756006390001e41c5 100644 (file)
@@ -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 <fs_name>"')
+
+
+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())
index ec7e838af52f2a58460a378dc43c28483389f999..dc7f45c32c2b0cfa4ba3aaf006823c41d1aaff96 100644 (file)
@@ -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: