]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/services/rbd.py
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / services / rbd.py
1 # -*- coding: utf-8 -*-
2 from __future__ import absolute_import
3
4 import six
5
6 import rbd
7
8 from .. import mgr
9
10
11 RBD_FEATURES_NAME_MAPPING = {
12 rbd.RBD_FEATURE_LAYERING: "layering",
13 rbd.RBD_FEATURE_STRIPINGV2: "striping",
14 rbd.RBD_FEATURE_EXCLUSIVE_LOCK: "exclusive-lock",
15 rbd.RBD_FEATURE_OBJECT_MAP: "object-map",
16 rbd.RBD_FEATURE_FAST_DIFF: "fast-diff",
17 rbd.RBD_FEATURE_DEEP_FLATTEN: "deep-flatten",
18 rbd.RBD_FEATURE_JOURNALING: "journaling",
19 rbd.RBD_FEATURE_DATA_POOL: "data-pool",
20 rbd.RBD_FEATURE_OPERATIONS: "operations",
21 }
22
23
24 def format_bitmask(features):
25 """
26 Formats the bitmask:
27
28 >>> format_bitmask(45)
29 ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']
30 """
31 names = [val for key, val in RBD_FEATURES_NAME_MAPPING.items()
32 if key & features == key]
33 return sorted(names)
34
35
36 def format_features(features):
37 """
38 Converts the features list to bitmask:
39
40 >>> format_features(['deep-flatten', 'exclusive-lock', 'layering', 'object-map'])
41 45
42
43 >>> format_features(None) is None
44 True
45
46 >>> format_features('deep-flatten, exclusive-lock')
47 32
48 """
49 if isinstance(features, six.string_types):
50 features = features.split(',')
51
52 if not isinstance(features, list):
53 return None
54
55 res = 0
56 for key, value in RBD_FEATURES_NAME_MAPPING.items():
57 if value in features:
58 res = key | res
59 return res
60
61
62 class RbdConfiguration(object):
63 _rbd = rbd.RBD()
64
65 def __init__(self, pool_name='', image_name='', pool_ioctx=None, image_ioctx=None):
66 # type: (str, str, object, object) -> None
67 assert bool(pool_name) != bool(pool_ioctx) # xor
68 self._pool_name = pool_name
69 self._image_name = image_name
70 self._pool_ioctx = pool_ioctx
71 self._image_ioctx = image_ioctx
72
73 @staticmethod
74 def _ensure_prefix(option):
75 # type: (str) -> str
76 return option if option.startswith('conf_') else 'conf_' + option
77
78 def list(self):
79 # type: () -> [dict]
80 def _list(ioctx):
81 if self._image_name: # image config
82 with rbd.Image(ioctx, self._image_name) as image:
83 result = image.config_list()
84 else: # pool config
85 result = self._rbd.config_list(ioctx)
86 return list(result)
87
88 if self._pool_name:
89 ioctx = mgr.rados.open_ioctx(self._pool_name)
90 else:
91 ioctx = self._pool_ioctx
92
93 return _list(ioctx)
94
95 def get(self, option_name):
96 # type: (str) -> str
97 option_name = self._ensure_prefix(option_name)
98 with mgr.rados.open_ioctx(self._pool_name) as pool_ioctx:
99 if self._image_name:
100 with rbd.Image(pool_ioctx, self._image_name) as image:
101 return image.metadata_get(option_name)
102 return self._rbd.pool_metadata_get(pool_ioctx, option_name)
103
104 def set(self, option_name, option_value):
105 # type: (str, str) -> None
106
107 option_value = str(option_value)
108 option_name = self._ensure_prefix(option_name)
109
110 pool_ioctx = self._pool_ioctx
111 if self._pool_name: # open ioctx
112 pool_ioctx = mgr.rados.open_ioctx(self._pool_name)
113 pool_ioctx.__enter__()
114
115 image_ioctx = self._image_ioctx
116 if self._image_name:
117 image_ioctx = rbd.Image(pool_ioctx, self._image_name)
118 image_ioctx.__enter__()
119
120 if image_ioctx:
121 image_ioctx.metadata_set(option_name, option_value)
122 else:
123 self._rbd.pool_metadata_set(pool_ioctx, option_name, option_value)
124
125 if self._image_name: # Name provided, so we opened it and now have to close it
126 image_ioctx.__exit__(None, None, None)
127 if self._pool_name:
128 pool_ioctx.__exit__(None, None, None)
129
130 def remove(self, option_name):
131 """
132 Removes an option by name. Will not raise an error, if the option hasn't been found.
133 :type option_name str
134 """
135 def _remove(ioctx):
136 try:
137 if self._image_name:
138 with rbd.Image(ioctx, self._image_name) as image:
139 image.metadata_remove(option_name)
140 else:
141 self._rbd.pool_metadata_remove(ioctx, option_name)
142 except KeyError:
143 pass
144
145 option_name = self._ensure_prefix(option_name)
146
147 if self._pool_name:
148 with mgr.rados.open_ioctx(self._pool_name) as pool_ioctx:
149 _remove(pool_ioctx)
150 else:
151 _remove(self._pool_ioctx)
152
153 def set_configuration(self, configuration):
154 if configuration:
155 for option_name, option_value in configuration.items():
156 if option_value is not None:
157 self.set(option_name, option_value)
158 else:
159 self.remove(option_name)