diff options
Diffstat (limited to '')
-rw-r--r-- | src/pybind/mgr/dashboard/services/rbd.py | 72 |
1 files changed, 58 insertions, 14 deletions
diff --git a/src/pybind/mgr/dashboard/services/rbd.py b/src/pybind/mgr/dashboard/services/rbd.py index 2c255a4fcb6..07b4db9e6a4 100644 --- a/src/pybind/mgr/dashboard/services/rbd.py +++ b/src/pybind/mgr/dashboard/services/rbd.py @@ -1,11 +1,14 @@ # -*- coding: utf-8 -*- # pylint: disable=unused-argument import errno +import json +from enum import IntEnum import cherrypy import rbd from .. import mgr +from ..exceptions import DashboardException from ..tools import ViewCache from .ceph_service import CephService @@ -28,6 +31,20 @@ RBD_FEATURES_NAME_MAPPING = { } +class MIRROR_IMAGE_MODE(IntEnum): + journal = rbd.RBD_MIRROR_IMAGE_MODE_JOURNAL + snapshot = rbd.RBD_MIRROR_IMAGE_MODE_SNAPSHOT + + +def _rbd_support_remote(method_name: str, *args, **kwargs): + try: + return mgr.remote('rbd_support', method_name, *args, **kwargs) + except ImportError as ie: + raise DashboardException(f'rbd_support module not found {ie}') + except RuntimeError as ie: + raise DashboardException(f'rbd_support.{method_name} error: {ie}') + + def format_bitmask(features): """ Formats the bitmask: @@ -245,10 +262,22 @@ class RbdService(object): return total_used_size, snap_map @classmethod - def _rbd_image(cls, ioctx, pool_name, namespace, image_name): + def _rbd_image(cls, ioctx, pool_name, namespace, image_name): # pylint: disable=R0912 with rbd.Image(ioctx, image_name) as img: - stat = img.stat() + mirror_mode = img.mirror_image_get_mode() + if mirror_mode == rbd.RBD_MIRROR_IMAGE_MODE_JOURNAL: + stat['mirror_mode'] = 'journal' + elif mirror_mode == rbd.RBD_MIRROR_IMAGE_MODE_SNAPSHOT: + stat['mirror_mode'] = 'snapshot' + schedule_status = json.loads(_rbd_support_remote( + 'mirror_snapshot_schedule_status')[1]) + for scheduled_image in schedule_status['scheduled_images']: + if scheduled_image['image'] == get_image_spec(pool_name, namespace, image_name): + stat['schedule_info'] = scheduled_image + else: + stat['mirror_mode'] = 'unknown' + stat['name'] = image_name if img.old_format(): stat['unique_id'] = get_image_spec(pool_name, namespace, stat['block_name_prefix']) @@ -286,23 +315,34 @@ class RbdService(object): # snapshots stat['snapshots'] = [] for snap in img.list_snaps(): + try: + snap['mirror_mode'] = MIRROR_IMAGE_MODE(img.mirror_image_get_mode()).name + except ValueError as ex: + raise DashboardException(f'Unknown RBD Mirror mode: {ex}') + snap['timestamp'] = "{}Z".format( img.get_snap_timestamp(snap['id']).isoformat()) - snap['is_protected'] = img.is_protected_snap(snap['name']) + + snap['is_protected'] = None + if mirror_mode != rbd.RBD_MIRROR_IMAGE_MODE_SNAPSHOT: + snap['is_protected'] = img.is_protected_snap(snap['name']) snap['used_bytes'] = None snap['children'] = [] - img.set_snap(snap['name']) - for child_pool_name, child_image_name in img.list_children(): - snap['children'].append({ - 'pool_name': child_pool_name, - 'image_name': child_image_name - }) + + if mirror_mode != rbd.RBD_MIRROR_IMAGE_MODE_SNAPSHOT: + img.set_snap(snap['name']) + for child_pool_name, child_image_name in img.list_children(): + snap['children'].append({ + 'pool_name': child_pool_name, + 'image_name': child_image_name + }) stat['snapshots'].append(snap) # disk usage img_flags = img.flags() if 'fast-diff' in stat['features_name'] and \ - not rbd.RBD_FLAG_FAST_DIFF_INVALID & img_flags: + not rbd.RBD_FLAG_FAST_DIFF_INVALID & img_flags and \ + mirror_mode != rbd.RBD_MIRROR_IMAGE_MODE_SNAPSHOT: snaps = [(s['id'], s['size'], s['name']) for s in stat['snapshots']] snaps.sort(key=lambda s: s[0]) @@ -431,7 +471,7 @@ class RBDSchedulerInterval: class RbdMirroringService: @classmethod - def enable_image(cls, image_name: str, pool_name: str, namespace: str, mode: str): + def enable_image(cls, image_name: str, pool_name: str, namespace: str, mode: MIRROR_IMAGE_MODE): rbd_image_call(pool_name, namespace, image_name, lambda ioctx, image: image.mirror_image_enable(mode)) @@ -456,6 +496,10 @@ class RbdMirroringService: lambda ioctx, image: image.mirror_image_resync()) @classmethod - def snapshot_schedule(cls, image_spec: str, interval: str, start_time: str = ''): - mgr.remote('rbd_support', 'mirror_snapshot_schedule_add', image_spec, - str(RBDSchedulerInterval(interval)), start_time) + def snapshot_schedule_add(cls, image_spec: str, interval: str): + _rbd_support_remote('mirror_snapshot_schedule_add', image_spec, + str(RBDSchedulerInterval(interval))) + + @classmethod + def snapshot_schedule_remove(cls, image_spec: str): + _rbd_support_remote('mirror_snapshot_schedule_remove', image_spec) |