]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | # -*- coding: utf-8 -*- |
2 | # pylint: disable=too-many-public-methods | |
3 | ||
4 | from __future__ import absolute_import | |
5 | ||
6 | import time | |
7 | ||
f67539c2 | 8 | from .helper import DashboardTestCase, JLeaf, JList, JObj |
11fdf7f2 TL |
9 | |
10 | ||
11 | class RbdTest(DashboardTestCase): | |
f67539c2 | 12 | AUTH_ROLES = ['pool-manager', 'block-manager', 'cluster-manager'] |
2a845540 | 13 | LIST_VERSION = '2.0' |
11fdf7f2 TL |
14 | |
15 | @DashboardTestCase.RunAs('test', 'test', [{'rbd-image': ['create', 'update', 'delete']}]) | |
16 | def test_read_access_permissions(self): | |
2a845540 TL |
17 | self._get('/api/block/image?offset=0&limit=-1&search=&sort=+name', |
18 | version=RbdTest.LIST_VERSION) | |
11fdf7f2 | 19 | self.assertStatus(403) |
9f95a23c | 20 | self.get_image('pool', None, 'image') |
11fdf7f2 TL |
21 | self.assertStatus(403) |
22 | ||
23 | @DashboardTestCase.RunAs('test', 'test', [{'rbd-image': ['read', 'update', 'delete']}]) | |
24 | def test_create_access_permissions(self): | |
9f95a23c | 25 | self.create_image('pool', None, 'name', 0) |
11fdf7f2 | 26 | self.assertStatus(403) |
1e59de90 | 27 | self.create_snapshot('pool', None, 'image', 'snapshot', False) |
11fdf7f2 | 28 | self.assertStatus(403) |
9f95a23c | 29 | self.copy_image('src_pool', None, 'src_image', 'dest_pool', None, 'dest_image') |
11fdf7f2 | 30 | self.assertStatus(403) |
9f95a23c | 31 | self.clone_image('parent_pool', None, 'parent_image', 'parent_snap', 'pool', None, 'name') |
11fdf7f2 TL |
32 | self.assertStatus(403) |
33 | ||
34 | @DashboardTestCase.RunAs('test', 'test', [{'rbd-image': ['read', 'create', 'delete']}]) | |
35 | def test_update_access_permissions(self): | |
9f95a23c | 36 | self.edit_image('pool', None, 'image') |
11fdf7f2 | 37 | self.assertStatus(403) |
9f95a23c | 38 | self.update_snapshot('pool', None, 'image', 'snapshot', None, None) |
11fdf7f2 | 39 | self.assertStatus(403) |
9f95a23c | 40 | self.rollback_snapshot('rbd', None, 'rollback_img', 'snap1') |
11fdf7f2 | 41 | self.assertStatus(403) |
9f95a23c | 42 | self.flatten_image('pool', None, 'image') |
11fdf7f2 TL |
43 | self.assertStatus(403) |
44 | ||
45 | @DashboardTestCase.RunAs('test', 'test', [{'rbd-image': ['read', 'create', 'update']}]) | |
46 | def test_delete_access_permissions(self): | |
9f95a23c | 47 | self.remove_image('pool', None, 'image') |
11fdf7f2 | 48 | self.assertStatus(403) |
9f95a23c | 49 | self.remove_snapshot('pool', None, 'image', 'snapshot') |
11fdf7f2 TL |
50 | self.assertStatus(403) |
51 | ||
52 | @classmethod | |
9f95a23c TL |
53 | def create_namespace(cls, pool, namespace): |
54 | data = {'namespace': namespace} | |
55 | return cls._post('/api/block/pool/{}/namespace'.format(pool), data) | |
56 | ||
57 | @classmethod | |
58 | def remove_namespace(cls, pool, namespace): | |
59 | return cls._delete('/api/block/pool/{}/namespace/{}'.format(pool, namespace)) | |
60 | ||
61 | @classmethod | |
62 | def create_image(cls, pool, namespace, name, size, **kwargs): | |
63 | data = {'name': name, 'pool_name': pool, 'namespace': namespace, 'size': size} | |
11fdf7f2 TL |
64 | data.update(kwargs) |
65 | return cls._task_post('/api/block/image', data) | |
66 | ||
67 | @classmethod | |
9f95a23c TL |
68 | def get_image(cls, pool, namespace, name): |
69 | namespace = '{}%2F'.format(namespace) if namespace else '' | |
70 | return cls._get('/api/block/image/{}%2F{}{}'.format(pool, namespace, name)) | |
71 | ||
72 | @classmethod | |
73 | def clone_image(cls, parent_pool, parent_namespace, parent_image, parent_snap, pool, namespace, | |
74 | name, **kwargs): | |
11fdf7f2 | 75 | # pylint: disable=too-many-arguments |
9f95a23c | 76 | data = {'child_image_name': name, 'child_namespace': namespace, 'child_pool_name': pool} |
11fdf7f2 | 77 | data.update(kwargs) |
9f95a23c TL |
78 | parent_namespace = '{}%2F'.format(parent_namespace) if parent_namespace else '' |
79 | return cls._task_post('/api/block/image/{}%2F{}{}/snap/{}/clone' | |
80 | .format(parent_pool, parent_namespace, parent_image, parent_snap), | |
11fdf7f2 TL |
81 | data) |
82 | ||
83 | @classmethod | |
9f95a23c TL |
84 | def copy_image(cls, src_pool, src_namespace, src_image, dest_pool, dest_namespace, dest_image, |
85 | **kwargs): | |
11fdf7f2 | 86 | # pylint: disable=too-many-arguments |
9f95a23c TL |
87 | data = {'dest_image_name': dest_image, |
88 | 'dest_pool_name': dest_pool, | |
89 | 'dest_namespace': dest_namespace} | |
11fdf7f2 | 90 | data.update(kwargs) |
9f95a23c TL |
91 | src_namespace = '{}%2F'.format(src_namespace) if src_namespace else '' |
92 | return cls._task_post('/api/block/image/{}%2F{}{}/copy' | |
93 | .format(src_pool, src_namespace, src_image), data) | |
11fdf7f2 TL |
94 | |
95 | @classmethod | |
9f95a23c TL |
96 | def remove_image(cls, pool, namespace, image): |
97 | namespace = '{}%2F'.format(namespace) if namespace else '' | |
98 | return cls._task_delete('/api/block/image/{}%2F{}{}'.format(pool, namespace, image)) | |
11fdf7f2 TL |
99 | |
100 | # pylint: disable=too-many-arguments | |
101 | @classmethod | |
9f95a23c | 102 | def edit_image(cls, pool, namespace, image, name=None, size=None, features=None, **kwargs): |
11fdf7f2 | 103 | kwargs.update({'name': name, 'size': size, 'features': features}) |
9f95a23c TL |
104 | namespace = '{}%2F'.format(namespace) if namespace else '' |
105 | return cls._task_put('/api/block/image/{}%2F{}{}'.format(pool, namespace, image), kwargs) | |
11fdf7f2 TL |
106 | |
107 | @classmethod | |
9f95a23c TL |
108 | def flatten_image(cls, pool, namespace, image): |
109 | namespace = '{}%2F'.format(namespace) if namespace else '' | |
110 | return cls._task_post('/api/block/image/{}%2F{}{}/flatten'.format(pool, namespace, image)) | |
11fdf7f2 TL |
111 | |
112 | @classmethod | |
1e59de90 | 113 | def create_snapshot(cls, pool, namespace, image, snapshot, mirrorImageSnapshot): |
9f95a23c TL |
114 | namespace = '{}%2F'.format(namespace) if namespace else '' |
115 | return cls._task_post('/api/block/image/{}%2F{}{}/snap'.format(pool, namespace, image), | |
1e59de90 | 116 | {'snapshot_name': snapshot, 'mirrorImageSnapshot': mirrorImageSnapshot}) # noqa E501 #pylint: disable=line-too-long |
11fdf7f2 TL |
117 | |
118 | @classmethod | |
9f95a23c TL |
119 | def remove_snapshot(cls, pool, namespace, image, snapshot): |
120 | namespace = '{}%2F'.format(namespace) if namespace else '' | |
121 | return cls._task_delete('/api/block/image/{}%2F{}{}/snap/{}'.format(pool, namespace, image, | |
122 | snapshot)) | |
11fdf7f2 TL |
123 | |
124 | @classmethod | |
9f95a23c TL |
125 | def update_snapshot(cls, pool, namespace, image, snapshot, new_name, is_protected): |
126 | namespace = '{}%2F'.format(namespace) if namespace else '' | |
127 | return cls._task_put('/api/block/image/{}%2F{}{}/snap/{}'.format(pool, namespace, image, | |
128 | snapshot), | |
11fdf7f2 TL |
129 | {'new_snap_name': new_name, 'is_protected': is_protected}) |
130 | ||
9f95a23c TL |
131 | @classmethod |
132 | def rollback_snapshot(cls, pool, namespace, image, snapshot): | |
133 | namespace = '{}%2F'.format(namespace) if namespace else '' | |
134 | return cls._task_post('/api/block/image/{}%2F{}{}/snap/{}/rollback'.format(pool, | |
135 | namespace, | |
136 | image, | |
137 | snapshot)) | |
138 | ||
11fdf7f2 TL |
139 | @classmethod |
140 | def setUpClass(cls): | |
141 | super(RbdTest, cls).setUpClass() | |
eafe8130 TL |
142 | cls.create_pool('rbd', 2**3, 'replicated') |
143 | cls.create_pool('rbd_iscsi', 2**3, 'replicated') | |
11fdf7f2 | 144 | |
9f95a23c TL |
145 | cls.create_image('rbd', None, 'img1', 2**30) |
146 | cls.create_image('rbd', None, 'img2', 2*2**30) | |
147 | cls.create_image('rbd_iscsi', None, 'img1', 2**30) | |
148 | cls.create_image('rbd_iscsi', None, 'img2', 2*2**30) | |
11fdf7f2 TL |
149 | |
150 | osd_metadata = cls.ceph_cluster.mon_manager.get_osd_metadata() | |
151 | cls.bluestore_support = True | |
152 | for osd in osd_metadata: | |
153 | if osd['osd_objectstore'] != 'bluestore': | |
154 | cls.bluestore_support = False | |
155 | break | |
156 | ||
157 | @classmethod | |
158 | def tearDownClass(cls): | |
159 | super(RbdTest, cls).tearDownClass() | |
160 | cls._ceph_cmd(['osd', 'pool', 'delete', 'rbd', 'rbd', '--yes-i-really-really-mean-it']) | |
161 | cls._ceph_cmd(['osd', 'pool', 'delete', 'rbd_iscsi', 'rbd_iscsi', | |
162 | '--yes-i-really-really-mean-it']) | |
163 | cls._ceph_cmd(['osd', 'pool', 'delete', 'rbd_data', 'rbd_data', | |
164 | '--yes-i-really-really-mean-it']) | |
165 | ||
f6b5b4d7 TL |
166 | def create_image_in_trash(self, pool, name, delay=0): |
167 | self.create_image(pool, None, name, 10240) | |
168 | img = self._get('/api/block/image/{}%2F{}'.format(pool, name)) | |
11fdf7f2 | 169 | |
f6b5b4d7 | 170 | self._task_post("/api/block/image/{}%2F{}/move_trash".format(pool, name), |
f67539c2 | 171 | {'delay': delay}) |
f6b5b4d7 | 172 | self.assertStatus([200, 201]) |
11fdf7f2 TL |
173 | return img['id'] |
174 | ||
175 | @classmethod | |
9f95a23c TL |
176 | def remove_trash(cls, pool, image_id, force=False): |
177 | return cls._task_delete('/api/block/image/trash/{}%2F{}/?force={}'.format( | |
178 | pool, image_id, force)) | |
179 | ||
180 | @classmethod | |
181 | def restore_trash(cls, pool, namespace, image_id, new_image_name): | |
182 | data = {'new_image_name': new_image_name} | |
183 | namespace = '{}%2F'.format(namespace) if namespace else '' | |
184 | return cls._task_post('/api/block/image/trash/{}%2F{}{}/restore'.format(pool, | |
185 | namespace, | |
186 | image_id), data) | |
187 | ||
188 | @classmethod | |
189 | def purge_trash(cls, pool): | |
190 | return cls._task_post('/api/block/image/trash/purge?pool_name={}'.format(pool)) | |
11fdf7f2 TL |
191 | |
192 | @classmethod | |
193 | def get_trash(cls, pool, image_id): | |
194 | trash = cls._get('/api/block/image/trash/?pool_name={}'.format(pool)) | |
195 | if isinstance(trash, list): | |
f67539c2 TL |
196 | for trash_pool in trash: |
197 | for image in trash_pool['value']: | |
11fdf7f2 TL |
198 | if image['id'] == image_id: |
199 | return image | |
200 | ||
201 | return None | |
202 | ||
203 | def _validate_image(self, img, **kwargs): | |
204 | """ | |
205 | Example of an RBD image json: | |
206 | ||
207 | { | |
208 | "size": 1073741824, | |
209 | "obj_size": 4194304, | |
2a845540 | 210 | "mirror_mode": "journal", |
11fdf7f2 TL |
211 | "num_objs": 256, |
212 | "order": 22, | |
213 | "block_name_prefix": "rbd_data.10ae2ae8944a", | |
214 | "name": "img1", | |
215 | "pool_name": "rbd", | |
216 | "features": 61, | |
1e59de90 | 217 | "primary": true, |
11fdf7f2 TL |
218 | "features_name": ["deep-flatten", "exclusive-lock", "fast-diff", "layering", |
219 | "object-map"] | |
220 | } | |
221 | """ | |
222 | schema = JObj(sub_elems={ | |
223 | 'size': JLeaf(int), | |
224 | 'obj_size': JLeaf(int), | |
225 | 'num_objs': JLeaf(int), | |
226 | 'order': JLeaf(int), | |
227 | 'block_name_prefix': JLeaf(str), | |
228 | 'name': JLeaf(str), | |
229 | 'id': JLeaf(str), | |
f6b5b4d7 TL |
230 | 'unique_id': JLeaf(str), |
231 | 'image_format': JLeaf(int), | |
11fdf7f2 | 232 | 'pool_name': JLeaf(str), |
9f95a23c | 233 | 'namespace': JLeaf(str, none=True), |
1e59de90 | 234 | 'primary': JLeaf(bool, none=True), |
11fdf7f2 TL |
235 | 'features': JLeaf(int), |
236 | 'features_name': JList(JLeaf(str)), | |
237 | 'stripe_count': JLeaf(int, none=True), | |
238 | 'stripe_unit': JLeaf(int, none=True), | |
f78120f9 TL |
239 | 'parent': JObj(sub_elems={'pool_id': JLeaf(int), |
240 | 'pool_name': JLeaf(str), | |
9f95a23c | 241 | 'pool_namespace': JLeaf(str, none=True), |
f78120f9 | 242 | 'image_id': JLeaf(str), |
11fdf7f2 | 243 | 'image_name': JLeaf(str), |
f78120f9 TL |
244 | 'trash': JLeaf(bool), |
245 | 'snap_id': JLeaf(int), | |
246 | 'snap_namespace_type': JLeaf(int), | |
11fdf7f2 TL |
247 | 'snap_name': JLeaf(str)}, none=True), |
248 | 'data_pool': JLeaf(str, none=True), | |
249 | 'snapshots': JList(JLeaf(dict)), | |
250 | 'timestamp': JLeaf(str, none=True), | |
251 | 'disk_usage': JLeaf(int, none=True), | |
252 | 'total_disk_usage': JLeaf(int, none=True), | |
253 | 'configuration': JList(JObj(sub_elems={ | |
254 | 'name': JLeaf(str), | |
255 | 'source': JLeaf(int), | |
256 | 'value': JLeaf(str), | |
257 | })), | |
1e59de90 | 258 | 'metadata': JObj({}, allow_unknown=True), |
2a845540 | 259 | 'mirror_mode': JLeaf(str), |
11fdf7f2 TL |
260 | }) |
261 | self.assertSchema(img, schema) | |
262 | ||
263 | for k, v in kwargs.items(): | |
f78120f9 TL |
264 | if k == 'parent' and v is not None: |
265 | # check that img['parent'] contains (is a superset of) v | |
266 | actual = {pk: img['parent'][pk] | |
267 | for pk in v.keys() if pk in img['parent']} | |
268 | self.assertEqual(actual, v) | |
269 | elif isinstance(v, list): | |
11fdf7f2 TL |
270 | self.assertSetEqual(set(img[k]), set(v)) |
271 | else: | |
272 | self.assertEqual(img[k], v) | |
273 | ||
274 | def _validate_snapshot(self, snap, **kwargs): | |
275 | self.assertIn('id', snap) | |
276 | self.assertIn('name', snap) | |
277 | self.assertIn('is_protected', snap) | |
278 | self.assertIn('timestamp', snap) | |
279 | self.assertIn('size', snap) | |
280 | self.assertIn('children', snap) | |
281 | ||
282 | for k, v in kwargs.items(): | |
283 | if isinstance(v, list): | |
284 | self.assertSetEqual(set(snap[k]), set(v)) | |
285 | else: | |
286 | self.assertEqual(snap[k], v) | |
287 | ||
288 | def _validate_snapshot_list(self, snap_list, snap_name=None, **kwargs): | |
289 | found = False | |
290 | for snap in snap_list: | |
291 | self.assertIn('name', snap) | |
292 | if snap_name and snap['name'] == snap_name: | |
293 | found = True | |
294 | self._validate_snapshot(snap, **kwargs) | |
295 | break | |
296 | if snap_name and not found: | |
297 | self.fail("Snapshot {} not found".format(snap_name)) | |
298 | ||
299 | def test_list(self): | |
2a845540 TL |
300 | data = self._get('/api/block/image?offset=0&limit=-1&search=&sort=+name', |
301 | version=RbdTest.LIST_VERSION) | |
11fdf7f2 TL |
302 | self.assertStatus(200) |
303 | self.assertEqual(len(data), 2) | |
304 | ||
305 | for pool_view in data: | |
11fdf7f2 TL |
306 | self.assertIsNotNone(pool_view['value']) |
307 | self.assertIn('pool_name', pool_view) | |
308 | self.assertIn(pool_view['pool_name'], ['rbd', 'rbd_iscsi']) | |
309 | image_list = pool_view['value'] | |
310 | self.assertEqual(len(image_list), 2) | |
311 | ||
312 | for img in image_list: | |
313 | self.assertIn('name', img) | |
314 | self.assertIn('pool_name', img) | |
315 | self.assertIn(img['pool_name'], ['rbd', 'rbd_iscsi']) | |
316 | if img['name'] == 'img1': | |
317 | self._validate_image(img, size=1073741824, | |
318 | num_objs=256, obj_size=4194304, | |
319 | features_name=['deep-flatten', | |
320 | 'exclusive-lock', | |
321 | 'fast-diff', | |
322 | 'layering', | |
323 | 'object-map']) | |
324 | elif img['name'] == 'img2': | |
325 | self._validate_image(img, size=2147483648, | |
326 | num_objs=512, obj_size=4194304, | |
327 | features_name=['deep-flatten', | |
328 | 'exclusive-lock', | |
329 | 'fast-diff', | |
330 | 'layering', | |
331 | 'object-map']) | |
332 | else: | |
333 | assert False, "Unexcepted image '{}' in result list".format(img['name']) | |
334 | ||
335 | def test_create(self): | |
336 | rbd_name = 'test_rbd' | |
9f95a23c | 337 | self.create_image('rbd', None, rbd_name, 10240) |
11fdf7f2 TL |
338 | self.assertStatus(201) |
339 | ||
9f95a23c | 340 | img = self.get_image('rbd', None, 'test_rbd') |
11fdf7f2 TL |
341 | self.assertStatus(200) |
342 | ||
343 | self._validate_image(img, name=rbd_name, size=10240, | |
344 | num_objs=1, obj_size=4194304, | |
345 | features_name=['deep-flatten', | |
346 | 'exclusive-lock', | |
347 | 'fast-diff', 'layering', | |
348 | 'object-map']) | |
349 | ||
9f95a23c | 350 | self.remove_image('rbd', None, rbd_name) |
11fdf7f2 TL |
351 | |
352 | def test_create_with_configuration(self): | |
353 | pool = 'rbd' | |
354 | image_name = 'image_with_config' | |
355 | size = 10240 | |
356 | configuration = { | |
357 | 'rbd_qos_bps_limit': 10240, | |
358 | 'rbd_qos_bps_burst': 10240 * 2, | |
359 | } | |
360 | expected = [{ | |
361 | 'name': 'rbd_qos_bps_limit', | |
362 | 'source': 2, | |
363 | 'value': str(10240), | |
364 | }, { | |
365 | 'name': 'rbd_qos_bps_burst', | |
366 | 'source': 2, | |
367 | 'value': str(10240 * 2), | |
368 | }] | |
369 | ||
9f95a23c | 370 | self.create_image(pool, None, image_name, size, configuration=configuration) |
11fdf7f2 | 371 | self.assertStatus(201) |
9f95a23c | 372 | img = self.get_image('rbd', None, image_name) |
11fdf7f2 TL |
373 | self.assertStatus(200) |
374 | for conf in expected: | |
375 | self.assertIn(conf, img['configuration']) | |
376 | ||
9f95a23c | 377 | self.remove_image(pool, None, image_name) |
11fdf7f2 | 378 | |
1e59de90 TL |
379 | def test_create_with_metadata(self): |
380 | pool = 'rbd' | |
381 | image_name = 'image_with_meta' | |
382 | size = 10240 | |
383 | metadata = { | |
384 | 'test1': 'test', | |
385 | 'test2': 'value', | |
386 | } | |
387 | ||
388 | self.create_image(pool, None, image_name, size, metadata=metadata) | |
389 | self.assertStatus(201) | |
390 | img = self.get_image('rbd', None, image_name) | |
391 | self.assertStatus(200) | |
392 | self.assertEqual(len(metadata), len(img['metadata'])) | |
393 | for meta in metadata: | |
394 | self.assertIn(meta, img['metadata']) | |
395 | ||
396 | self.remove_image(pool, None, image_name) | |
397 | ||
11fdf7f2 TL |
398 | def test_create_rbd_in_data_pool(self): |
399 | if not self.bluestore_support: | |
400 | self.skipTest('requires bluestore cluster') | |
401 | ||
eafe8130 | 402 | self.create_pool('data_pool', 2**4, 'erasure') |
11fdf7f2 TL |
403 | |
404 | rbd_name = 'test_rbd_in_data_pool' | |
9f95a23c | 405 | self.create_image('rbd', None, rbd_name, 10240, data_pool='data_pool') |
11fdf7f2 TL |
406 | self.assertStatus(201) |
407 | ||
9f95a23c | 408 | img = self.get_image('rbd', None, 'test_rbd_in_data_pool') |
11fdf7f2 TL |
409 | self.assertStatus(200) |
410 | ||
411 | self._validate_image(img, name=rbd_name, size=10240, | |
412 | num_objs=1, obj_size=4194304, | |
413 | data_pool='data_pool', | |
414 | features_name=['data-pool', 'deep-flatten', | |
415 | 'exclusive-lock', | |
416 | 'fast-diff', 'layering', | |
417 | 'object-map']) | |
418 | ||
9f95a23c | 419 | self.remove_image('rbd', None, rbd_name) |
11fdf7f2 TL |
420 | self.assertStatus(204) |
421 | self._ceph_cmd(['osd', 'pool', 'delete', 'data_pool', 'data_pool', | |
422 | '--yes-i-really-really-mean-it']) | |
423 | ||
424 | def test_create_rbd_twice(self): | |
9f95a23c | 425 | res = self.create_image('rbd', None, 'test_rbd_twice', 10240) |
11fdf7f2 | 426 | |
9f95a23c | 427 | res = self.create_image('rbd', None, 'test_rbd_twice', 10240) |
11fdf7f2 TL |
428 | self.assertStatus(400) |
429 | self.assertEqual(res, {"code": '17', 'status': 400, "component": "rbd", | |
f67539c2 TL |
430 | "detail": "[errno 17] RBD image already exists (error creating " |
431 | "image)", | |
11fdf7f2 | 432 | 'task': {'name': 'rbd/create', |
9f95a23c | 433 | 'metadata': {'pool_name': 'rbd', 'namespace': None, |
11fdf7f2 | 434 | 'image_name': 'test_rbd_twice'}}}) |
9f95a23c | 435 | self.remove_image('rbd', None, 'test_rbd_twice') |
11fdf7f2 TL |
436 | self.assertStatus(204) |
437 | ||
438 | def test_snapshots_and_clone_info(self): | |
1e59de90 TL |
439 | self.create_snapshot('rbd', None, 'img1', 'snap1', False) |
440 | self.create_snapshot('rbd', None, 'img1', 'snap2', False) | |
11fdf7f2 TL |
441 | self._rbd_cmd(['snap', 'protect', 'rbd/img1@snap1']) |
442 | self._rbd_cmd(['clone', 'rbd/img1@snap1', 'rbd_iscsi/img1_clone']) | |
443 | ||
9f95a23c | 444 | img = self.get_image('rbd', None, 'img1') |
11fdf7f2 TL |
445 | self.assertStatus(200) |
446 | self._validate_image(img, name='img1', size=1073741824, | |
447 | num_objs=256, obj_size=4194304, parent=None, | |
448 | features_name=['deep-flatten', 'exclusive-lock', | |
449 | 'fast-diff', 'layering', | |
450 | 'object-map']) | |
451 | for snap in img['snapshots']: | |
452 | if snap['name'] == 'snap1': | |
453 | self._validate_snapshot(snap, is_protected=True) | |
454 | self.assertEqual(len(snap['children']), 1) | |
455 | self.assertDictEqual(snap['children'][0], | |
456 | {'pool_name': 'rbd_iscsi', | |
457 | 'image_name': 'img1_clone'}) | |
458 | elif snap['name'] == 'snap2': | |
459 | self._validate_snapshot(snap, is_protected=False) | |
460 | ||
9f95a23c | 461 | img = self.get_image('rbd_iscsi', None, 'img1_clone') |
11fdf7f2 TL |
462 | self.assertStatus(200) |
463 | self._validate_image(img, name='img1_clone', size=1073741824, | |
464 | num_objs=256, obj_size=4194304, | |
9f95a23c TL |
465 | parent={'pool_name': 'rbd', 'pool_namespace': '', |
466 | 'image_name': 'img1', 'snap_name': 'snap1'}, | |
11fdf7f2 TL |
467 | features_name=['deep-flatten', 'exclusive-lock', |
468 | 'fast-diff', 'layering', | |
469 | 'object-map']) | |
9f95a23c | 470 | self.remove_image('rbd_iscsi', None, 'img1_clone') |
11fdf7f2 TL |
471 | self.assertStatus(204) |
472 | ||
473 | def test_disk_usage(self): | |
474 | self._rbd_cmd(['bench', '--io-type', 'write', '--io-total', '50M', 'rbd/img2']) | |
1e59de90 | 475 | self.create_snapshot('rbd', None, 'img2', 'snap1', False) |
11fdf7f2 | 476 | self._rbd_cmd(['bench', '--io-type', 'write', '--io-total', '20M', 'rbd/img2']) |
1e59de90 | 477 | self.create_snapshot('rbd', None, 'img2', 'snap2', False) |
11fdf7f2 | 478 | self._rbd_cmd(['bench', '--io-type', 'write', '--io-total', '10M', 'rbd/img2']) |
1e59de90 | 479 | self.create_snapshot('rbd', None, 'img2', 'snap3', False) |
11fdf7f2 | 480 | self._rbd_cmd(['bench', '--io-type', 'write', '--io-total', '5M', 'rbd/img2']) |
9f95a23c | 481 | img = self.get_image('rbd', None, 'img2') |
11fdf7f2 TL |
482 | self.assertStatus(200) |
483 | self._validate_image(img, name='img2', size=2147483648, | |
484 | total_disk_usage=268435456, disk_usage=67108864) | |
485 | ||
486 | def test_delete_non_existent_image(self): | |
9f95a23c TL |
487 | res = self.remove_image('rbd', None, 'i_dont_exist') |
488 | self.assertStatus(404) | |
489 | self.assertEqual(res, {u'code': 404, "status": 404, "component": None, | |
490 | "detail": "(404, 'Image not found')", | |
11fdf7f2 | 491 | 'task': {'name': 'rbd/delete', |
9f95a23c | 492 | 'metadata': {'image_spec': 'rbd/i_dont_exist'}}}) |
11fdf7f2 TL |
493 | |
494 | def test_image_delete(self): | |
9f95a23c | 495 | self.create_image('rbd', None, 'delete_me', 2**30) |
11fdf7f2 | 496 | self.assertStatus(201) |
1e59de90 | 497 | self.create_snapshot('rbd', None, 'delete_me', 'snap1', False) |
11fdf7f2 | 498 | self.assertStatus(201) |
1e59de90 | 499 | self.create_snapshot('rbd', None, 'delete_me', 'snap2', False) |
11fdf7f2 TL |
500 | self.assertStatus(201) |
501 | ||
9f95a23c | 502 | img = self.get_image('rbd', None, 'delete_me') |
11fdf7f2 TL |
503 | self.assertStatus(200) |
504 | self._validate_image(img, name='delete_me', size=2**30) | |
505 | self.assertEqual(len(img['snapshots']), 2) | |
506 | ||
9f95a23c | 507 | self.remove_snapshot('rbd', None, 'delete_me', 'snap1') |
11fdf7f2 | 508 | self.assertStatus(204) |
9f95a23c | 509 | self.remove_snapshot('rbd', None, 'delete_me', 'snap2') |
11fdf7f2 TL |
510 | self.assertStatus(204) |
511 | ||
9f95a23c | 512 | img = self.get_image('rbd', None, 'delete_me') |
11fdf7f2 TL |
513 | self.assertStatus(200) |
514 | self._validate_image(img, name='delete_me', size=2**30) | |
515 | self.assertEqual(len(img['snapshots']), 0) | |
516 | ||
9f95a23c TL |
517 | self.remove_image('rbd', None, 'delete_me') |
518 | self.assertStatus(204) | |
519 | ||
520 | def test_image_delete_with_snapshot(self): | |
521 | self.create_image('rbd', None, 'delete_me', 2**30) | |
522 | self.assertStatus(201) | |
1e59de90 | 523 | self.create_snapshot('rbd', None, 'delete_me', 'snap1', False) |
9f95a23c | 524 | self.assertStatus(201) |
1e59de90 | 525 | self.create_snapshot('rbd', None, 'delete_me', 'snap2', False) |
9f95a23c TL |
526 | self.assertStatus(201) |
527 | ||
528 | img = self.get_image('rbd', None, 'delete_me') | |
529 | self.assertStatus(200) | |
530 | self._validate_image(img, name='delete_me', size=2**30) | |
531 | self.assertEqual(len(img['snapshots']), 2) | |
532 | ||
533 | self.remove_image('rbd', None, 'delete_me') | |
11fdf7f2 TL |
534 | self.assertStatus(204) |
535 | ||
536 | def test_image_rename(self): | |
9f95a23c | 537 | self.create_image('rbd', None, 'edit_img', 2**30) |
11fdf7f2 | 538 | self.assertStatus(201) |
9f95a23c | 539 | self.get_image('rbd', None, 'edit_img') |
11fdf7f2 | 540 | self.assertStatus(200) |
9f95a23c | 541 | self.edit_image('rbd', None, 'edit_img', 'new_edit_img') |
11fdf7f2 | 542 | self.assertStatus(200) |
9f95a23c | 543 | self.get_image('rbd', None, 'edit_img') |
11fdf7f2 | 544 | self.assertStatus(404) |
9f95a23c | 545 | self.get_image('rbd', None, 'new_edit_img') |
11fdf7f2 | 546 | self.assertStatus(200) |
9f95a23c | 547 | self.remove_image('rbd', None, 'new_edit_img') |
11fdf7f2 TL |
548 | self.assertStatus(204) |
549 | ||
550 | def test_image_resize(self): | |
9f95a23c | 551 | self.create_image('rbd', None, 'edit_img', 2**30) |
11fdf7f2 | 552 | self.assertStatus(201) |
9f95a23c | 553 | img = self.get_image('rbd', None, 'edit_img') |
11fdf7f2 TL |
554 | self.assertStatus(200) |
555 | self._validate_image(img, size=2**30) | |
9f95a23c | 556 | self.edit_image('rbd', None, 'edit_img', size=2*2**30) |
11fdf7f2 | 557 | self.assertStatus(200) |
9f95a23c | 558 | img = self.get_image('rbd', None, 'edit_img') |
11fdf7f2 TL |
559 | self.assertStatus(200) |
560 | self._validate_image(img, size=2*2**30) | |
9f95a23c | 561 | self.remove_image('rbd', None, 'edit_img') |
11fdf7f2 TL |
562 | self.assertStatus(204) |
563 | ||
564 | def test_image_change_features(self): | |
9f95a23c | 565 | self.create_image('rbd', None, 'edit_img', 2**30, features=["layering"]) |
11fdf7f2 | 566 | self.assertStatus(201) |
9f95a23c | 567 | img = self.get_image('rbd', None, 'edit_img') |
11fdf7f2 TL |
568 | self.assertStatus(200) |
569 | self._validate_image(img, features_name=["layering"]) | |
9f95a23c | 570 | self.edit_image('rbd', None, 'edit_img', |
11fdf7f2 | 571 | features=["fast-diff", "object-map", "exclusive-lock"]) |
81eedcae | 572 | self.assertStatus(200) |
9f95a23c | 573 | img = self.get_image('rbd', None, 'edit_img') |
11fdf7f2 TL |
574 | self.assertStatus(200) |
575 | self._validate_image(img, features_name=['exclusive-lock', | |
576 | 'fast-diff', 'layering', | |
577 | 'object-map']) | |
9f95a23c | 578 | self.edit_image('rbd', None, 'edit_img', |
11fdf7f2 | 579 | features=["journaling", "exclusive-lock"]) |
81eedcae | 580 | self.assertStatus(200) |
9f95a23c | 581 | img = self.get_image('rbd', None, 'edit_img') |
11fdf7f2 TL |
582 | self.assertStatus(200) |
583 | self._validate_image(img, features_name=['exclusive-lock', | |
584 | 'journaling', 'layering']) | |
9f95a23c | 585 | self.remove_image('rbd', None, 'edit_img') |
11fdf7f2 TL |
586 | self.assertStatus(204) |
587 | ||
588 | def test_image_change_config(self): | |
589 | pool = 'rbd' | |
590 | image = 'image_with_config' | |
591 | initial_conf = { | |
592 | 'rbd_qos_bps_limit': 10240, | |
593 | 'rbd_qos_write_iops_limit': None | |
594 | } | |
595 | initial_expect = [{ | |
596 | 'name': 'rbd_qos_bps_limit', | |
597 | 'source': 2, | |
598 | 'value': '10240', | |
599 | }, { | |
600 | 'name': 'rbd_qos_write_iops_limit', | |
601 | 'source': 0, | |
602 | 'value': '0', | |
603 | }] | |
604 | new_conf = { | |
605 | 'rbd_qos_bps_limit': 0, | |
606 | 'rbd_qos_bps_burst': 20480, | |
607 | 'rbd_qos_write_iops_limit': None | |
608 | } | |
609 | new_expect = [{ | |
610 | 'name': 'rbd_qos_bps_limit', | |
611 | 'source': 2, | |
612 | 'value': '0', | |
613 | }, { | |
614 | 'name': 'rbd_qos_bps_burst', | |
615 | 'source': 2, | |
616 | 'value': '20480', | |
617 | }, { | |
618 | 'name': 'rbd_qos_write_iops_limit', | |
619 | 'source': 0, | |
620 | 'value': '0', | |
621 | }] | |
622 | ||
9f95a23c | 623 | self.create_image(pool, None, image, 2**30, configuration=initial_conf) |
11fdf7f2 | 624 | self.assertStatus(201) |
9f95a23c | 625 | img = self.get_image(pool, None, image) |
11fdf7f2 TL |
626 | self.assertStatus(200) |
627 | for conf in initial_expect: | |
628 | self.assertIn(conf, img['configuration']) | |
629 | ||
9f95a23c TL |
630 | self.edit_image(pool, None, image, configuration=new_conf) |
631 | img = self.get_image(pool, None, image) | |
11fdf7f2 TL |
632 | self.assertStatus(200) |
633 | for conf in new_expect: | |
634 | self.assertIn(conf, img['configuration']) | |
635 | ||
9f95a23c | 636 | self.remove_image(pool, None, image) |
11fdf7f2 TL |
637 | self.assertStatus(204) |
638 | ||
1e59de90 TL |
639 | def test_image_change_meta(self): |
640 | pool = 'rbd' | |
641 | image = 'image_with_meta' | |
642 | initial_meta = { | |
643 | 'test1': 'test', | |
644 | 'test2': 'value', | |
645 | 'test3': None, | |
646 | } | |
647 | initial_expect = { | |
648 | 'test1': 'test', | |
649 | 'test2': 'value', | |
650 | } | |
651 | new_meta = { | |
652 | 'test1': None, | |
653 | 'test2': 'new_value', | |
654 | 'test3': 'value', | |
655 | 'test4': None, | |
656 | } | |
657 | new_expect = { | |
658 | 'test2': 'new_value', | |
659 | 'test3': 'value', | |
660 | } | |
661 | ||
662 | self.create_image(pool, None, image, 2**30, metadata=initial_meta) | |
663 | self.assertStatus(201) | |
664 | img = self.get_image(pool, None, image) | |
665 | self.assertStatus(200) | |
666 | self.assertEqual(len(initial_expect), len(img['metadata'])) | |
667 | for meta in initial_expect: | |
668 | self.assertIn(meta, img['metadata']) | |
669 | ||
670 | self.edit_image(pool, None, image, metadata=new_meta) | |
671 | img = self.get_image(pool, None, image) | |
672 | self.assertStatus(200) | |
673 | self.assertEqual(len(new_expect), len(img['metadata'])) | |
674 | for meta in new_expect: | |
675 | self.assertIn(meta, img['metadata']) | |
676 | ||
677 | self.remove_image(pool, None, image) | |
678 | self.assertStatus(204) | |
679 | ||
11fdf7f2 | 680 | def test_update_snapshot(self): |
1e59de90 | 681 | self.create_snapshot('rbd', None, 'img1', 'snap5', False) |
11fdf7f2 | 682 | self.assertStatus(201) |
9f95a23c | 683 | img = self.get_image('rbd', None, 'img1') |
11fdf7f2 TL |
684 | self._validate_snapshot_list(img['snapshots'], 'snap5', is_protected=False) |
685 | ||
9f95a23c | 686 | self.update_snapshot('rbd', None, 'img1', 'snap5', 'snap6', None) |
11fdf7f2 | 687 | self.assertStatus(200) |
9f95a23c | 688 | img = self.get_image('rbd', None, 'img1') |
11fdf7f2 TL |
689 | self._validate_snapshot_list(img['snapshots'], 'snap6', is_protected=False) |
690 | ||
9f95a23c | 691 | self.update_snapshot('rbd', None, 'img1', 'snap6', None, True) |
11fdf7f2 | 692 | self.assertStatus(200) |
9f95a23c | 693 | img = self.get_image('rbd', None, 'img1') |
11fdf7f2 TL |
694 | self._validate_snapshot_list(img['snapshots'], 'snap6', is_protected=True) |
695 | ||
9f95a23c | 696 | self.update_snapshot('rbd', None, 'img1', 'snap6', 'snap5', False) |
11fdf7f2 | 697 | self.assertStatus(200) |
9f95a23c | 698 | img = self.get_image('rbd', None, 'img1') |
11fdf7f2 TL |
699 | self._validate_snapshot_list(img['snapshots'], 'snap5', is_protected=False) |
700 | ||
9f95a23c | 701 | self.remove_snapshot('rbd', None, 'img1', 'snap5') |
11fdf7f2 TL |
702 | self.assertStatus(204) |
703 | ||
704 | def test_snapshot_rollback(self): | |
9f95a23c | 705 | self.create_image('rbd', None, 'rollback_img', 2**30, |
11fdf7f2 TL |
706 | features=["layering", "exclusive-lock", "fast-diff", |
707 | "object-map"]) | |
708 | self.assertStatus(201) | |
1e59de90 | 709 | self.create_snapshot('rbd', None, 'rollback_img', 'snap1', False) |
11fdf7f2 TL |
710 | self.assertStatus(201) |
711 | ||
9f95a23c | 712 | img = self.get_image('rbd', None, 'rollback_img') |
11fdf7f2 TL |
713 | self.assertStatus(200) |
714 | self.assertEqual(img['disk_usage'], 0) | |
715 | ||
716 | self._rbd_cmd(['bench', '--io-type', 'write', '--io-total', '5M', | |
717 | 'rbd/rollback_img']) | |
718 | ||
9f95a23c | 719 | img = self.get_image('rbd', None, 'rollback_img') |
11fdf7f2 TL |
720 | self.assertStatus(200) |
721 | self.assertGreater(img['disk_usage'], 0) | |
722 | ||
9f95a23c | 723 | self.rollback_snapshot('rbd', None, 'rollback_img', 'snap1') |
11fdf7f2 TL |
724 | self.assertStatus([201, 200]) |
725 | ||
9f95a23c | 726 | img = self.get_image('rbd', None, 'rollback_img') |
11fdf7f2 TL |
727 | self.assertStatus(200) |
728 | self.assertEqual(img['disk_usage'], 0) | |
729 | ||
9f95a23c | 730 | self.remove_snapshot('rbd', None, 'rollback_img', 'snap1') |
11fdf7f2 | 731 | self.assertStatus(204) |
9f95a23c | 732 | self.remove_image('rbd', None, 'rollback_img') |
11fdf7f2 TL |
733 | self.assertStatus(204) |
734 | ||
735 | def test_clone(self): | |
1e59de90 TL |
736 | self.create_image('rbd', None, 'cimg', 2**30, features=["layering"], |
737 | metadata={'key1': 'val1'}) | |
11fdf7f2 | 738 | self.assertStatus(201) |
1e59de90 | 739 | self.create_snapshot('rbd', None, 'cimg', 'snap1', False) |
11fdf7f2 | 740 | self.assertStatus(201) |
9f95a23c | 741 | self.update_snapshot('rbd', None, 'cimg', 'snap1', None, True) |
11fdf7f2 | 742 | self.assertStatus(200) |
9f95a23c | 743 | self.clone_image('rbd', None, 'cimg', 'snap1', 'rbd', None, 'cimg-clone', |
11fdf7f2 | 744 | features=["layering", "exclusive-lock", "fast-diff", |
1e59de90 TL |
745 | "object-map"], |
746 | metadata={'key1': None, 'key2': 'val2'}) | |
11fdf7f2 TL |
747 | self.assertStatus([200, 201]) |
748 | ||
9f95a23c | 749 | img = self.get_image('rbd', None, 'cimg-clone') |
11fdf7f2 TL |
750 | self.assertStatus(200) |
751 | self._validate_image(img, features_name=['exclusive-lock', | |
752 | 'fast-diff', 'layering', | |
753 | 'object-map'], | |
9f95a23c | 754 | parent={'pool_name': 'rbd', 'pool_namespace': '', |
1e59de90 TL |
755 | 'image_name': 'cimg', 'snap_name': 'snap1'}, |
756 | metadata={'key2': 'val2'}) | |
11fdf7f2 | 757 | |
9f95a23c | 758 | res = self.remove_image('rbd', None, 'cimg') |
11fdf7f2 TL |
759 | self.assertStatus(400) |
760 | self.assertIn('code', res) | |
9f95a23c | 761 | self.assertEqual(res['code'], '16') |
11fdf7f2 | 762 | |
9f95a23c | 763 | self.remove_image('rbd', None, 'cimg-clone') |
11fdf7f2 | 764 | self.assertStatus(204) |
9f95a23c | 765 | self.remove_image('rbd', None, 'cimg') |
11fdf7f2 TL |
766 | self.assertStatus(204) |
767 | ||
768 | def test_copy(self): | |
9f95a23c | 769 | self.create_image('rbd', None, 'coimg', 2**30, |
11fdf7f2 | 770 | features=["layering", "exclusive-lock", "fast-diff", |
1e59de90 TL |
771 | "object-map"], |
772 | metadata={'key1': 'val1'}) | |
11fdf7f2 TL |
773 | self.assertStatus(201) |
774 | ||
775 | self._rbd_cmd(['bench', '--io-type', 'write', '--io-total', '5M', | |
776 | 'rbd/coimg']) | |
777 | ||
9f95a23c | 778 | self.copy_image('rbd', None, 'coimg', 'rbd_iscsi', None, 'coimg-copy', |
11fdf7f2 | 779 | features=["layering", "fast-diff", "exclusive-lock", |
1e59de90 TL |
780 | "object-map"], |
781 | metadata={'key1': None, 'key2': 'val2'}) | |
11fdf7f2 TL |
782 | self.assertStatus([200, 201]) |
783 | ||
9f95a23c | 784 | img = self.get_image('rbd', None, 'coimg') |
11fdf7f2 TL |
785 | self.assertStatus(200) |
786 | self._validate_image(img, features_name=['layering', 'exclusive-lock', | |
1e59de90 TL |
787 | 'fast-diff', 'object-map'], |
788 | metadata={'key1': 'val1'}) | |
11fdf7f2 | 789 | |
9f95a23c | 790 | img_copy = self.get_image('rbd_iscsi', None, 'coimg-copy') |
11fdf7f2 TL |
791 | self._validate_image(img_copy, features_name=['exclusive-lock', |
792 | 'fast-diff', 'layering', | |
793 | 'object-map'], | |
1e59de90 | 794 | metadata={'key2': 'val2'}, |
11fdf7f2 TL |
795 | disk_usage=img['disk_usage']) |
796 | ||
9f95a23c | 797 | self.remove_image('rbd', None, 'coimg') |
11fdf7f2 | 798 | self.assertStatus(204) |
9f95a23c | 799 | self.remove_image('rbd_iscsi', None, 'coimg-copy') |
11fdf7f2 TL |
800 | self.assertStatus(204) |
801 | ||
802 | def test_flatten(self): | |
1e59de90 | 803 | self.create_snapshot('rbd', None, 'img1', 'snapf', False) |
9f95a23c TL |
804 | self.update_snapshot('rbd', None, 'img1', 'snapf', None, True) |
805 | self.clone_image('rbd', None, 'img1', 'snapf', 'rbd_iscsi', None, 'img1_snapf_clone') | |
11fdf7f2 | 806 | |
9f95a23c | 807 | img = self.get_image('rbd_iscsi', None, 'img1_snapf_clone') |
11fdf7f2 TL |
808 | self.assertStatus(200) |
809 | self.assertIsNotNone(img['parent']) | |
810 | ||
9f95a23c | 811 | self.flatten_image('rbd_iscsi', None, 'img1_snapf_clone') |
11fdf7f2 TL |
812 | self.assertStatus([200, 201]) |
813 | ||
9f95a23c | 814 | img = self.get_image('rbd_iscsi', None, 'img1_snapf_clone') |
11fdf7f2 TL |
815 | self.assertStatus(200) |
816 | self.assertIsNone(img['parent']) | |
817 | ||
9f95a23c TL |
818 | self.update_snapshot('rbd', None, 'img1', 'snapf', None, False) |
819 | self.remove_snapshot('rbd', None, 'img1', 'snapf') | |
11fdf7f2 TL |
820 | self.assertStatus(204) |
821 | ||
9f95a23c | 822 | self.remove_image('rbd_iscsi', None, 'img1_snapf_clone') |
11fdf7f2 TL |
823 | self.assertStatus(204) |
824 | ||
825 | def test_default_features(self): | |
826 | default_features = self._get('/api/block/image/default_features') | |
9f95a23c TL |
827 | self.assertEqual(default_features, [ |
828 | 'deep-flatten', 'exclusive-lock', 'fast-diff', 'layering', 'object-map']) | |
11fdf7f2 | 829 | |
f67539c2 TL |
830 | def test_clone_format_version(self): |
831 | config_name = 'rbd_default_clone_format' | |
832 | ||
833 | def _get_config_by_name(conf_name): | |
834 | data = self._get('/api/cluster_conf/{}'.format(conf_name)) | |
835 | if 'value' in data: | |
836 | return data['value'] | |
837 | return None | |
838 | ||
839 | # with rbd_default_clone_format = auto | |
840 | clone_format_version = self._get('/api/block/image/clone_format_version') | |
841 | self.assertEqual(clone_format_version, 1) | |
842 | self.assertStatus(200) | |
843 | ||
844 | # with rbd_default_clone_format = 1 | |
845 | value = [{'section': "global", 'value': "1"}] | |
846 | self._post('/api/cluster_conf', { | |
847 | 'name': config_name, | |
848 | 'value': value | |
849 | }) | |
850 | self.wait_until_equal( | |
851 | lambda: _get_config_by_name(config_name), | |
852 | value, | |
853 | timeout=60) | |
854 | clone_format_version = self._get('/api/block/image/clone_format_version') | |
855 | self.assertEqual(clone_format_version, 1) | |
856 | self.assertStatus(200) | |
857 | ||
858 | # with rbd_default_clone_format = 2 | |
859 | value = [{'section': "global", 'value': "2"}] | |
860 | self._post('/api/cluster_conf', { | |
861 | 'name': config_name, | |
862 | 'value': value | |
863 | }) | |
864 | self.wait_until_equal( | |
865 | lambda: _get_config_by_name(config_name), | |
866 | value, | |
867 | timeout=60) | |
868 | clone_format_version = self._get('/api/block/image/clone_format_version') | |
869 | self.assertEqual(clone_format_version, 2) | |
870 | self.assertStatus(200) | |
871 | ||
872 | value = [] | |
873 | self._post('/api/cluster_conf', { | |
874 | 'name': config_name, | |
875 | 'value': value | |
876 | }) | |
877 | self.wait_until_equal( | |
878 | lambda: _get_config_by_name(config_name), | |
879 | None, | |
880 | timeout=60) | |
881 | ||
9f95a23c TL |
882 | def test_image_with_namespace(self): |
883 | self.create_namespace('rbd', 'ns') | |
884 | self.create_image('rbd', 'ns', 'test', 10240) | |
11fdf7f2 TL |
885 | self.assertStatus(201) |
886 | ||
9f95a23c | 887 | img = self.get_image('rbd', 'ns', 'test') |
11fdf7f2 TL |
888 | self.assertStatus(200) |
889 | ||
9f95a23c TL |
890 | self._validate_image(img, name='test', size=10240, |
891 | pool_name='rbd', namespace='ns', | |
11fdf7f2 TL |
892 | num_objs=1, obj_size=4194304, |
893 | features_name=['deep-flatten', | |
894 | 'exclusive-lock', | |
895 | 'fast-diff', 'layering', | |
896 | 'object-map']) | |
897 | ||
9f95a23c TL |
898 | self.remove_image('rbd', 'ns', 'test') |
899 | self.remove_namespace('rbd', 'ns') | |
11fdf7f2 TL |
900 | |
901 | def test_move_image_to_trash(self): | |
f67539c2 | 902 | img_id = self.create_image_in_trash('rbd', 'test_rbd') |
11fdf7f2 | 903 | |
9f95a23c | 904 | self.get_image('rbd', None, 'test_rbd') |
11fdf7f2 TL |
905 | self.assertStatus(404) |
906 | ||
907 | time.sleep(1) | |
908 | ||
f67539c2 | 909 | image = self.get_trash('rbd', img_id) |
11fdf7f2 TL |
910 | self.assertIsNotNone(image) |
911 | ||
f67539c2 | 912 | self.remove_trash('rbd', img_id) |
11fdf7f2 TL |
913 | |
914 | def test_list_trash(self): | |
f67539c2 | 915 | img_id = self.create_image_in_trash('rbd', 'test_rbd', 0) |
11fdf7f2 TL |
916 | data = self._get('/api/block/image/trash/?pool_name={}'.format('rbd')) |
917 | self.assertStatus(200) | |
918 | self.assertIsInstance(data, list) | |
919 | self.assertIsNotNone(data) | |
920 | ||
f67539c2 | 921 | self.remove_trash('rbd', img_id) |
11fdf7f2 TL |
922 | self.assertStatus(204) |
923 | ||
924 | def test_restore_trash(self): | |
f67539c2 | 925 | img_id = self.create_image_in_trash('rbd', 'test_rbd') |
11fdf7f2 | 926 | |
f67539c2 | 927 | self.restore_trash('rbd', None, img_id, 'test_rbd') |
11fdf7f2 | 928 | |
9f95a23c | 929 | self.get_image('rbd', None, 'test_rbd') |
11fdf7f2 TL |
930 | self.assertStatus(200) |
931 | ||
f67539c2 | 932 | image = self.get_trash('rbd', img_id) |
11fdf7f2 TL |
933 | self.assertIsNone(image) |
934 | ||
9f95a23c | 935 | self.remove_image('rbd', None, 'test_rbd') |
11fdf7f2 TL |
936 | |
937 | def test_remove_expired_trash(self): | |
f67539c2 TL |
938 | img_id = self.create_image_in_trash('rbd', 'test_rbd', 0) |
939 | self.remove_trash('rbd', img_id, False) | |
11fdf7f2 TL |
940 | self.assertStatus(204) |
941 | ||
f67539c2 | 942 | image = self.get_trash('rbd', img_id) |
11fdf7f2 TL |
943 | self.assertIsNone(image) |
944 | ||
945 | def test_remove_not_expired_trash(self): | |
f67539c2 TL |
946 | img_id = self.create_image_in_trash('rbd', 'test_rbd', 9999) |
947 | self.remove_trash('rbd', img_id, False) | |
11fdf7f2 TL |
948 | self.assertStatus(400) |
949 | ||
950 | time.sleep(1) | |
951 | ||
f67539c2 | 952 | image = self.get_trash('rbd', img_id) |
11fdf7f2 TL |
953 | self.assertIsNotNone(image) |
954 | ||
f67539c2 | 955 | self.remove_trash('rbd', img_id, True) |
11fdf7f2 TL |
956 | |
957 | def test_remove_not_expired_trash_with_force(self): | |
f67539c2 TL |
958 | img_id = self.create_image_in_trash('rbd', 'test_rbd', 9999) |
959 | self.remove_trash('rbd', img_id, True) | |
11fdf7f2 TL |
960 | self.assertStatus(204) |
961 | ||
f67539c2 | 962 | image = self.get_trash('rbd', img_id) |
11fdf7f2 TL |
963 | self.assertIsNone(image) |
964 | ||
965 | def test_purge_trash(self): | |
966 | id_expired = self.create_image_in_trash('rbd', 'test_rbd_expired', 0) | |
967 | id_not_expired = self.create_image_in_trash('rbd', 'test_rbd', 9999) | |
968 | ||
969 | time.sleep(1) | |
970 | ||
9f95a23c | 971 | self.purge_trash('rbd') |
801d1391 | 972 | self.assertStatus([200, 201]) |
11fdf7f2 TL |
973 | |
974 | time.sleep(1) | |
975 | ||
976 | trash_not_expired = self.get_trash('rbd', id_not_expired) | |
977 | self.assertIsNotNone(trash_not_expired) | |
978 | ||
801d1391 | 979 | self.wait_until_equal(lambda: self.get_trash('rbd', id_expired), None, 60) |
9f95a23c TL |
980 | |
981 | def test_list_namespaces(self): | |
982 | self.create_namespace('rbd', 'ns') | |
983 | ||
984 | namespaces = self._get('/api/block/pool/rbd/namespace') | |
985 | self.assertStatus(200) | |
986 | self.assertEqual(len(namespaces), 1) | |
987 | ||
988 | self.remove_namespace('rbd', 'ns') |