1 # -*- coding: utf-8 -*-
2 from __future__
import absolute_import
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",
24 def format_bitmask(features
):
28 >>> format_bitmask(45)
29 ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']
31 names
= [val
for key
, val
in RBD_FEATURES_NAME_MAPPING
.items()
32 if key
& features
== key
]
36 def format_features(features
):
38 Converts the features list to bitmask:
40 >>> format_features(['deep-flatten', 'exclusive-lock', 'layering', 'object-map'])
43 >>> format_features(None) is None
46 >>> format_features('deep-flatten, exclusive-lock')
49 if isinstance(features
, six
.string_types
):
50 features
= features
.split(',')
52 if not isinstance(features
, list):
56 for key
, value
in RBD_FEATURES_NAME_MAPPING
.items():
62 class RbdConfiguration(object):
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
74 def _ensure_prefix(option
):
76 return option
if option
.startswith('conf_') else 'conf_' + option
81 if self
._image
_name
: # image config
82 with rbd
.Image(ioctx
, self
._image
_name
) as image
:
83 result
= image
.config_list()
85 result
= self
._rbd
.config_list(ioctx
)
89 ioctx
= mgr
.rados
.open_ioctx(self
._pool
_name
)
91 ioctx
= self
._pool
_ioctx
95 def get(self
, option_name
):
97 option_name
= self
._ensure
_prefix
(option_name
)
98 with mgr
.rados
.open_ioctx(self
._pool
_name
) as pool_ioctx
:
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
)
104 def set(self
, option_name
, option_value
):
105 # type: (str, str) -> None
107 option_value
= str(option_value
)
108 option_name
= self
._ensure
_prefix
(option_name
)
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
__()
115 image_ioctx
= self
._image
_ioctx
117 image_ioctx
= rbd
.Image(pool_ioctx
, self
._image
_name
)
118 image_ioctx
.__enter
__()
121 image_ioctx
.metadata_set(option_name
, option_value
)
123 self
._rbd
.pool_metadata_set(pool_ioctx
, option_name
, option_value
)
125 if self
._image
_name
: # Name provided, so we opened it and now have to close it
126 image_ioctx
.__exit
__(None, None, None)
128 pool_ioctx
.__exit
__(None, None, None)
130 def remove(self
, option_name
):
132 Removes an option by name. Will not raise an error, if the option hasn't been found.
133 :type option_name str
138 with rbd
.Image(ioctx
, self
._image
_name
) as image
:
139 image
.metadata_remove(option_name
)
141 self
._rbd
.pool_metadata_remove(ioctx
, option_name
)
145 option_name
= self
._ensure
_prefix
(option_name
)
148 with mgr
.rados
.open_ioctx(self
._pool
_name
) as pool_ioctx
:
151 _remove(self
._pool
_ioctx
)
153 def set_configuration(self
, configuration
):
155 for option_name
, option_value
in configuration
.items():
156 if option_value
is not None:
157 self
.set(option_name
, option_value
)
159 self
.remove(option_name
)