]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: iscsi: feature names in error messages 27363/head
authorRicardo Marques <rimarques@suse.com>
Mon, 25 Mar 2019 22:24:24 +0000 (22:24 +0000)
committerTatjana Dehler <tdehler@suse.com>
Thu, 4 Apr 2019 09:22:01 +0000 (11:22 +0200)
Required/supported RBD features should be included in
the error messages.

Signed-off-by: Ricardo Marques <rimarques@suse.com>
(cherry picked from commit f570f8a19ddc656c6df911eece77f7ed23720680)

src/pybind/mgr/dashboard/controllers/iscsi.py
src/pybind/mgr/dashboard/controllers/rbd.py
src/pybind/mgr/dashboard/services/rbd.py

index e684bef61aaee37653c5be495e02f6ee9fa91d6d..9b4c19dcf4e1b9635f4d57a9e7cdf99d256dd94d 100644 (file)
@@ -16,6 +16,7 @@ from ..rest_client import RequestException
 from ..security import Scope
 from ..services.iscsi_client import IscsiClient
 from ..services.iscsi_cli import IscsiGatewaysConfig
+from ..services.rbd import format_bitmask
 from ..exceptions import DashboardException
 from ..tools import TaskManager
 
@@ -365,13 +366,21 @@ class IscsiTarget(RESTController):
                     if img.features() & required_rbd_features != required_rbd_features:
                         raise DashboardException(msg='Image {} cannot be exported using {} '
                                                      'backstore because required features are '
-                                                     'missing'.format(image, backstore),
+                                                     'missing (required features are '
+                                                     '{})'.format(image,
+                                                                  backstore,
+                                                                  format_bitmask(
+                                                                      required_rbd_features)),
                                                  code='image_missing_required_features',
                                                  component='iscsi')
                     if img.features() & supported_rbd_features != img.features():
                         raise DashboardException(msg='Image {} cannot be exported using {} '
                                                      'backstore because it contains unsupported '
-                                                     'features'.format(image, backstore),
+                                                     'features (supported features are '
+                                                     '{})'.format(image,
+                                                                  backstore,
+                                                                  format_bitmask(
+                                                                      supported_rbd_features)),
                                                  code='image_contains_unsupported_features',
                                                  component='iscsi')
 
index 14a751b93c2c15efdad7052fbd87b72ee7a07345..ea1f2043d7e0c18abf8cebe8723c6144bda81c17 100644 (file)
@@ -8,7 +8,6 @@ from functools import partial
 from datetime import datetime
 
 import cherrypy
-import six
 
 import rbd
 
@@ -17,7 +16,7 @@ from . import ApiController, RESTController, Task, UpdatePermission, \
 from .. import mgr
 from ..security import Scope
 from ..services.ceph_service import CephService
-from ..services.rbd import RbdConfiguration
+from ..services.rbd import RbdConfiguration, format_bitmask, format_features
 from ..tools import ViewCache, str_to_bool
 from ..services.exception import handle_rados_error, handle_rbd_error, \
                                  serialize_dashboard_exception
@@ -46,57 +45,6 @@ def _rbd_image_call(pool_name, image_name, func, *args, **kwargs):
     return _rbd_call(pool_name, _ioctx_func, image_name, func, *args, **kwargs)
 
 
-RBD_FEATURES_NAME_MAPPING = {
-    rbd.RBD_FEATURE_LAYERING: "layering",
-    rbd.RBD_FEATURE_STRIPINGV2: "striping",
-    rbd.RBD_FEATURE_EXCLUSIVE_LOCK: "exclusive-lock",
-    rbd.RBD_FEATURE_OBJECT_MAP: "object-map",
-    rbd.RBD_FEATURE_FAST_DIFF: "fast-diff",
-    rbd.RBD_FEATURE_DEEP_FLATTEN: "deep-flatten",
-    rbd.RBD_FEATURE_JOURNALING: "journaling",
-    rbd.RBD_FEATURE_DATA_POOL: "data-pool",
-    rbd.RBD_FEATURE_OPERATIONS: "operations",
-}
-
-
-def _format_bitmask(features):
-    """
-    Formats the bitmask:
-
-    >>> _format_bitmask(45)
-    ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']
-    """
-    names = [val for key, val in RBD_FEATURES_NAME_MAPPING.items()
-             if key & features == key]
-    return sorted(names)
-
-
-def _format_features(features):
-    """
-    Converts the features list to bitmask:
-
-    >>> _format_features(['deep-flatten', 'exclusive-lock', 'layering', 'object-map'])
-    45
-
-    >>> _format_features(None) is None
-    True
-
-    >>> _format_features('deep-flatten, exclusive-lock')
-    32
-    """
-    if isinstance(features, six.string_types):
-        features = features.split(',')
-
-    if not isinstance(features, list):
-        return None
-
-    res = 0
-    for key, value in RBD_FEATURES_NAME_MAPPING.items():
-        if value in features:
-            res = key | res
-    return res
-
-
 def _sort_features(features, enable=True):
     """
     Sorts image features according to feature dependencies:
@@ -161,7 +109,7 @@ class Rbd(RESTController):
             stat['pool_name'] = pool_name
             features = img.features()
             stat['features'] = features
-            stat['features_name'] = _format_bitmask(features)
+            stat['features_name'] = format_bitmask(features)
 
             # the following keys are deprecated
             del stat['parent_pool']
@@ -294,7 +242,7 @@ class Rbd(RESTController):
                 l_order = int(round(math.log(float(obj_size), 2)))
 
             # Set features
-            feature_bitmask = _format_features(features)
+            feature_bitmask = format_features(features)
 
             rbd_inst.create(ioctx, name, size, order=l_order, old_format=False,
                             features=feature_bitmask, stripe_unit=stripe_unit,
@@ -322,18 +270,18 @@ class Rbd(RESTController):
 
             # check enable/disable features
             if features is not None:
-                curr_features = _format_bitmask(image.features())
+                curr_features = format_bitmask(image.features())
                 # check disabled features
                 _sort_features(curr_features, enable=False)
                 for feature in curr_features:
                     if feature not in features and feature in self.ALLOW_DISABLE_FEATURES:
-                        f_bitmask = _format_features([feature])
+                        f_bitmask = format_features([feature])
                         image.update_features(f_bitmask, False)
                 # check enabled features
                 _sort_features(features)
                 for feature in features:
                     if feature not in curr_features and feature in self.ALLOW_ENABLE_FEATURES:
-                        f_bitmask = _format_features([feature])
+                        f_bitmask = format_features([feature])
                         image.update_features(f_bitmask, True)
 
             RbdConfiguration(pool_ioctx=ioctx, image_name=image_name).set_configuration(
@@ -359,7 +307,7 @@ class Rbd(RESTController):
                     l_order = int(round(math.log(float(obj_size), 2)))
 
                 # Set features
-                feature_bitmask = _format_features(features)
+                feature_bitmask = format_features(features)
 
                 if snapshot_name:
                     s_img.set_snap(snapshot_name)
@@ -386,7 +334,7 @@ class Rbd(RESTController):
     @RESTController.Collection('GET')
     def default_features(self):
         rbd_default_features = mgr.get('config')['rbd_default_features']
-        return _format_bitmask(int(rbd_default_features))
+        return format_bitmask(int(rbd_default_features))
 
     @RbdTask('trash/move', ['{pool_name}', '{image_name}'], 2.0)
     @RESTController.Resource('POST')
@@ -475,7 +423,7 @@ class RbdSnapshot(RESTController):
                     l_order = int(round(math.log(float(obj_size), 2)))
 
                 # Set features
-                feature_bitmask = _format_features(features)
+                feature_bitmask = format_features(features)
 
                 rbd_inst = rbd.RBD()
                 rbd_inst.clone(p_ioctx, image_name, snapshot_name, ioctx,
index bdc536209ad6162603e8680dedb1b349602c5fcf..bb21e0abed8668e6da59117eb6e233577db670c2 100644 (file)
@@ -1,10 +1,64 @@
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
+import six
+
 import rbd
+
 from .. import mgr
 
 
+RBD_FEATURES_NAME_MAPPING = {
+    rbd.RBD_FEATURE_LAYERING: "layering",
+    rbd.RBD_FEATURE_STRIPINGV2: "striping",
+    rbd.RBD_FEATURE_EXCLUSIVE_LOCK: "exclusive-lock",
+    rbd.RBD_FEATURE_OBJECT_MAP: "object-map",
+    rbd.RBD_FEATURE_FAST_DIFF: "fast-diff",
+    rbd.RBD_FEATURE_DEEP_FLATTEN: "deep-flatten",
+    rbd.RBD_FEATURE_JOURNALING: "journaling",
+    rbd.RBD_FEATURE_DATA_POOL: "data-pool",
+    rbd.RBD_FEATURE_OPERATIONS: "operations",
+}
+
+
+def format_bitmask(features):
+    """
+    Formats the bitmask:
+
+    >>> format_bitmask(45)
+    ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']
+    """
+    names = [val for key, val in RBD_FEATURES_NAME_MAPPING.items()
+             if key & features == key]
+    return sorted(names)
+
+
+def format_features(features):
+    """
+    Converts the features list to bitmask:
+
+    >>> format_features(['deep-flatten', 'exclusive-lock', 'layering', 'object-map'])
+    45
+
+    >>> format_features(None) is None
+    True
+
+    >>> format_features('deep-flatten, exclusive-lock')
+    32
+    """
+    if isinstance(features, six.string_types):
+        features = features.split(',')
+
+    if not isinstance(features, list):
+        return None
+
+    res = 0
+    for key, value in RBD_FEATURES_NAME_MAPPING.items():
+        if value in features:
+            res = key | res
+    return res
+
+
 class RbdConfiguration(object):
     _rbd = rbd.RBD()