Codebase list cinder-tempest-plugin / bbb3cd6
Test srbac on backups Testing reader, member and admin roles. This file contains test 2 classes for API version 3.3 and 3.9 Signed-off-by: Yosi Ben Shimon <ybenshim@redhat.com> Change-Id: I9e6ea838fa7a93fcfc3d4ef7f807224aadee187b Yosi Ben Shimon 2 years ago
2 changed file(s) with 482 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
0
01 # Licensed under the Apache License, Version 2.0 (the "License"); you may
12 # not use this file except in compliance with the License. You may obtain
23 # a copy of the License at
2425 class VolumeV3RbacBaseTests(
2526 api_version_utils.BaseMicroversionTest, test.BaseTestCase
2627 ):
27
2828 identity_version = 'v3'
2929
3030 @classmethod
3939 if not CONF.service_available.cinder:
4040 skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
4141 raise cls.skipException(skip_msg)
42
4342 api_version_utils.check_skip_with_microversion(
4443 cls.min_microversion, cls.max_microversion,
4544 CONF.volume.min_microversion, CONF.volume.max_microversion)
159158 test_utils.call_and_ignore_notfound_exc(del_action, resource_id)
160159 test_utils.call_and_ignore_notfound_exc(
161160 client.wait_for_resource_deletion, resource_id)
161
162 @classmethod
163 def create_backup(
164 cls, volume_id, backup_client=None, add_cleanup=True, **kwargs
165 ):
166 """Wrapper utility that returns a test backup."""
167 if backup_client is None:
168 backup_client = cls.backups_client
169 if 'name' not in kwargs:
170 name = data_utils.rand_name(cls.__class__.__name__ + '-Backup')
171 kwargs['name'] = name
172
173 backup = backup_client.create_backup(
174 volume_id=volume_id, **kwargs
175 )['backup']
176 if add_cleanup:
177 cls.addClassResourceCleanup(
178 test_utils.call_and_ignore_notfound_exc,
179 cls.delete_resource,
180 client=backup_client,
181 backup_id=backup['id']
182 )
183 waiters.wait_for_volume_resource_status(
184 backup_client, backup['id'], 'available'
185 )
186 return backup
0 # Licensed under the Apache License, Version 2.0 (the "License"); you may
1 # not use this file except in compliance with the License. You may obtain
2 # a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
9 # License for the specific language governing permissions and limitations
10 # under the License.
11
12 from oslo_serialization import base64
13 from oslo_serialization import jsonutils as json
14
15 from tempest.common import waiters
16 from tempest import config
17 from tempest.lib.common.utils import data_utils
18 from tempest.lib import decorators
19 from tempest.lib import exceptions
20
21 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
22
23 CONF = config.CONF
24
25
26 class RbacV3BackupsTests(rbac_base.VolumeV3RbacBaseTests):
27 @classmethod
28 def skip_checks(cls):
29 super(RbacV3BackupsTests, cls).skip_checks()
30 if not CONF.volume_feature_enabled.backup:
31 raise cls.skipException("Cinder backup feature disabled")
32
33 @classmethod
34 def setup_clients(cls):
35 super().setup_clients()
36 admin_client = cls.os_project_admin
37 cls.admin_backups_client = admin_client.backups_client_latest
38 cls.admin_volumes_client = admin_client.volumes_client_latest
39
40 @classmethod
41 def resource_setup(cls):
42 super(RbacV3BackupsTests, cls).resource_setup()
43 cls.volume_id = cls.create_volume(client=cls.admin_volumes_client)
44 backup = cls.create_backup(
45 volume_id=cls.volume_id, backup_client=cls.admin_backups_client
46 )
47 cls.backup_id = backup['id']
48 cls.backup_name = backup['name']
49
50
51 class RbacV3BackupsTests33(RbacV3BackupsTests):
52 """Test API with microversion greater than 3.3"""
53 min_microversion = '3.3'
54
55 def _encode_backup(self, backup):
56 retval = json.dumps(backup)
57 return base64.encode_as_text(retval)
58
59 def _decode_url(self, backup_url):
60 return json.loads(base64.decode_as_text(backup_url))
61
62 def _modify_backup_url(self, backup_url, changes):
63 backup = self._decode_url(backup_url)
64 backup.update(changes)
65 return self._encode_backup(backup)
66
67 def _list_backups(self, expected_status):
68 """List all backups"""
69 backups = self.do_request(
70 method='list_backups', expected_status=expected_status
71 )['backups']
72 backup_list = [
73 b['id'] for b in backups if b['name'] == self.backup_name
74 ]
75
76 self.assertNotEmpty(
77 backup_list, f"Backup {self.backup_name} not found"
78 )
79
80 def _list_project_backups(self, expected_status):
81 """List all backups for a project"""
82 backups = self.do_request(
83 method='list_backups',
84 expected_status=expected_status,
85 project_id=self.client.project_id
86 )['backups']
87 backup_list = [
88 b['id'] for b in backups if b['name'] == self.backup_name
89 ]
90
91 self.assertNotEmpty(
92 backup_list, f"Backup {self.backup_name} not found"
93 )
94
95 def _show_backup(self, expected_status):
96 """Show backup details"""
97 backup = self.do_request(
98 method='show_backup',
99 expected_status=expected_status,
100 backup_id=self.backup_id
101 )['backup']
102 self.assertNotEmpty(backup, f"Backup {self.backup_name} not found")
103
104 def _delete_backup(self, expected_status):
105 """Delete a backup"""
106 add_cleanup = True if expected_status == exceptions.Forbidden\
107 else False
108 volume_id = self.create_volume(client=self.admin_volumes_client)
109 backup = self.create_backup(
110 volume_id=volume_id,
111 backup_client=self.admin_backups_client,
112 add_cleanup=add_cleanup
113 )
114
115 self.do_request(
116 method='delete_backup',
117 expected_status=expected_status,
118 backup_id=backup['id']
119 )
120
121 def _restore_backup(self, expected_status):
122 """Restore a backup"""
123 res = self.do_request(
124 method='restore_backup',
125 expected_status=expected_status,
126 backup_id=self.backup_id,
127 name='new-backup-vol'
128 )
129 if expected_status != exceptions.Forbidden:
130 waiters.wait_for_volume_resource_status(
131 self.admin_backups_client,
132 self.backup_id, 'available'
133 )
134 self.delete_resource(
135 client=self.admin_volumes_client,
136 volume_id=res['restore']['volume_id']
137 )
138
139 def _create_backup(self, expected_status):
140 """Create a backup"""
141 res = self.do_request(
142 method='create_backup',
143 expected_status=expected_status,
144 volume_id=self.volume_id
145 )
146 if expected_status != exceptions.Forbidden:
147 backup = res['backup']
148 waiters.wait_for_volume_resource_status(
149 self.admin_backups_client, backup['id'], 'available'
150 )
151 self.admin_backups_client.delete_backup(backup_id=backup['id'])
152
153 def _export_backup(self, expected_status):
154 """Export a backup"""
155 self.do_request(
156 method='export_backup',
157 expected_status=expected_status,
158 backup_id=self.backup_id
159 )
160
161 def _import_backup(self, expected_status):
162 """Import a backup"""
163 volume_id = self.create_volume(client=self.admin_volumes_client)
164 backup = self.create_backup(
165 volume_id=volume_id,
166 backup_client=self.admin_backups_client
167 )
168
169 export_backup = (
170 self.admin_backups_client.export_backup(
171 backup['id']
172 )['backup-record']
173 )
174 waiters.wait_for_volume_resource_status(
175 self.admin_backups_client, backup['id'], 'available'
176 )
177 self.assertTrue(
178 export_backup['backup_service'].startswith('cinder.backup.drivers')
179 )
180 # NOTE(ybenshim): Backups are imported with the same backup id
181 # (important for incremental backups among other things), so we cannot
182 # import the exported backup information as it is, because that Backup
183 # ID already exists. So we'll fake the data by changing the backup id
184 # in the exported backup DB info we have retrieved before importing it
185 # back.
186
187 new_id = data_utils.rand_uuid()
188 new_url = self._modify_backup_url(
189 export_backup['backup_url'], {'id': new_id})
190
191 res = self.do_request(
192 method='import_backup',
193 expected_status=expected_status,
194 backup_service=export_backup['backup_service'],
195 backup_url=new_url
196 )
197 if expected_status != exceptions.Forbidden:
198 new_backup = res['backup']
199 waiters.wait_for_volume_resource_status(
200 self.client, new_backup['id'], 'available'
201 )
202 self.delete_resource(
203 client=self.admin_backups_client,
204 backup_id=new_backup['id']
205 )
206
207 def _reset_backup_status(self, expected_status):
208 """Reset a backup status"""
209 new_status = 'error'
210 volume_id = self.create_volume(client=self.admin_volumes_client)
211 backup = self.create_backup(
212 volume_id=volume_id,
213 backup_client=self.admin_backups_client
214 )
215
216 self.do_request(
217 method='reset_backup_status',
218 expected_status=expected_status,
219 backup_id=backup['id'],
220 status=new_status
221 )
222
223
224 class ProjectReaderTests33(RbacV3BackupsTests33):
225 credentials = ['project_reader', 'project_admin']
226
227 @classmethod
228 def setup_clients(cls):
229 super().setup_clients()
230 cls.client = cls.os_project_reader.backups_client_latest
231
232 @decorators.idempotent_id('9dd02d4b-d6f8-45ca-a95e-534dbd586aab')
233 def test_list_backups(self):
234 """List all backups"""
235 self._list_backups(expected_status=200)
236
237 @decorators.idempotent_id('9ba2e970-c08b-4c1c-b912-2f3b1373ae6e')
238 def test_list_project_backups(self):
239 """List all backups for a project"""
240 self._list_project_backups(expected_status=200)
241
242 @decorators.idempotent_id('e88f8971-2892-4a54-80bb-dd21b18f19e9')
243 def test_show_backup(self):
244 """Show backup details"""
245 self._show_backup(expected_status=200)
246
247 @decorators.skip_because(bug='2017110')
248 @decorators.idempotent_id('a9ab3279-aa5e-4ad8-b740-b80a7769d3f9')
249 def test_delete_backup(self):
250 """Delete a backup"""
251 self._delete_backup(expected_status=exceptions.Forbidden)
252
253 @decorators.skip_because(bug='2017110')
254 @decorators.idempotent_id('0566fa4a-4e03-4cca-822f-d5a4922da2ab')
255 def test_restore_backup(self):
256 """Restore a backup"""
257 self._restore_backup(expected_status=exceptions.Forbidden)
258
259 @decorators.skip_because(bug='2017110')
260 @decorators.idempotent_id('bad2514e-18c0-4fa0-9e35-221182ee24cf')
261 def test_create_backup(self):
262 """Create a backup"""
263 self._create_backup(expected_status=exceptions.Forbidden)
264
265 @decorators.idempotent_id('ab74b8cc-5005-49b4-94f4-994567171b07')
266 def test_export_backup(self):
267 """Export a backup"""
268 self._export_backup(expected_status=exceptions.Forbidden)
269
270 @decorators.idempotent_id('caaa5756-261a-4d9c-bfc2-788719630a06')
271 def test_import_backup(self):
272 """Import a backup"""
273 self._import_backup(expected_status=exceptions.Forbidden)
274
275 @decorators.idempotent_id('c832ff77-8f22-499f-a7a3-0834972a1507')
276 def test_reset_backup_status(self):
277 """Reset a backup status"""
278 self._reset_backup_status(expected_status=exceptions.Forbidden)
279
280
281 class ProjectMemberTests33(RbacV3BackupsTests33):
282 credentials = ['project_member', 'project_admin']
283
284 @classmethod
285 def setup_clients(cls):
286 super().setup_clients()
287 cls.client = cls.os_project_member.backups_client_latest
288
289 @decorators.idempotent_id('5a23c53c-924b-47f6-a5d1-ab6327391c12')
290 def test_list_backups(self):
291 """List all backups"""
292 self._list_backups(expected_status=200)
293
294 @decorators.idempotent_id('c737bd7b-293c-4d8f-ada9-3b00f7e1adce')
295 def test_list_project_backups(self):
296 """List all backups for a project"""
297 self._list_project_backups(expected_status=200)
298
299 @decorators.idempotent_id('9944bb15-02fa-4321-97a4-ef8cb5b5fec2')
300 def test_show_backup(self):
301 """Show backup details"""
302 self._show_backup(expected_status=200)
303
304 @decorators.idempotent_id('c98dfea8-b9f2-4a84-947b-1d857c707789')
305 def test_delete_backup(self):
306 """Delete a backup"""
307 self._delete_backup(expected_status=202)
308
309 @decorators.idempotent_id('7a6fd066-00e7-4140-866c-8195fbd71e87')
310 def test_restore_backup(self):
311 """Restore a backup"""
312 self._restore_backup(expected_status=202)
313
314 @decorators.idempotent_id('44644140-4d05-4725-9a4b-6d1a71eda9b7')
315 def test_create_backup(self):
316 """Create a backup"""
317 self._create_backup(expected_status=202)
318
319 @decorators.idempotent_id('71c7cfaf-7809-4872-b1b2-3feb90b939d4')
320 def test_export_backup(self):
321 """Export a backup"""
322 self._export_backup(expected_status=exceptions.Forbidden)
323
324 @decorators.idempotent_id('f1c03c1b-2b48-4be0-8b6a-81df8a75f78c')
325 def test_import_backup(self):
326 """Import a backup"""
327 self._import_backup(expected_status=exceptions.Forbidden)
328
329 @decorators.idempotent_id('307f6fe9-81ed-444a-9aae-99a571d24bf5')
330 def test_reset_backup_status(self):
331 """Reset a backup status"""
332 self._reset_backup_status(expected_status=exceptions.Forbidden)
333
334
335 class ProjectAdminTests33(RbacV3BackupsTests33):
336 credentials = ['project_admin']
337
338 @classmethod
339 def setup_clients(cls):
340 super().setup_clients()
341 cls.client = cls.os_project_admin.backups_client_latest
342
343 @decorators.idempotent_id('81c579bc-db98-4773-9590-b742d0b00b89')
344 def test_list_backups(self):
345 """List all backups"""
346 self._list_backups(expected_status=200)
347
348 @decorators.idempotent_id('602dd42d-10df-4eb2-9664-3c9c44e3b35e')
349 def test_list_project_backups(self):
350 """List all backups for a project"""
351 self._list_project_backups(expected_status=200)
352
353 @decorators.idempotent_id('2094dcee-9585-4745-b045-a0f8c79fbe52')
354 def test_show_backup(self):
355 """Show backup details"""
356 self._show_backup(expected_status=200)
357
358 @decorators.idempotent_id('b77a8d69-1d12-480d-a83e-5f712d7c2b74')
359 def test_delete_backup(self):
360 """Delete a backup"""
361 self._delete_backup(expected_status=202)
362
363 @decorators.idempotent_id('7221d2df-338c-4932-be40-ad7166c03db1')
364 def test_restore_backup(self):
365 """Restore a backup"""
366 self._restore_backup(expected_status=202)
367
368 @decorators.idempotent_id('d347fa21-a5bf-4ce5-ab6b-246c3a06a735')
369 def test_create_backup(self):
370 """Create a backup"""
371 self._create_backup(expected_status=202)
372
373 @decorators.idempotent_id('e179a062-47d5-4fa8-b359-dedab2afddd8')
374 def test_export_backup(self):
375 """Export a backup"""
376 self._export_backup(expected_status=200)
377
378 @decorators.idempotent_id('1be80834-2463-49fb-a763-906e8c672fd5')
379 def test_import_backup(self):
380 """Import a backup"""
381 self._import_backup(expected_status=201)
382
383 @decorators.idempotent_id('88db5943-0053-489a-af30-12b139a38a0b')
384 def test_reset_backup_status(self):
385 """Reset a backup status"""
386 self._reset_backup_status(expected_status=202)
387
388
389 class RbacV3BackupsTests39(RbacV3BackupsTests):
390 """Test API with microversion greater than 3.3"""
391 min_microversion = '3.9'
392
393 def _update_backup(self, expected_status):
394 """Update a backup"""
395 new_description = "Updated backup description"
396 update_kwargs = {"description": new_description}
397 self.do_request(
398 method='update_backup',
399 expected_status=expected_status,
400 backup_id=self.backup_id,
401 **update_kwargs
402 )
403 if expected_status != exceptions.Forbidden:
404 backup = self.admin_backups_client.show_backup(
405 backup_id=self.backup_id
406 )['backup']
407 self.assertEqual(
408 backup['description'], new_description,
409 f"Backup {backup['name']} description should be "
410 f"{new_description}"
411 )
412
413
414 class ProjectReaderTests39(RbacV3BackupsTests39):
415 credentials = ['project_reader', 'project_admin']
416
417 @classmethod
418 def setup_clients(cls):
419 super().setup_clients()
420 cls.client = cls.os_project_reader.backups_client_latest
421
422 @decorators.idempotent_id('50ccc892-6ed0-4015-b181-9f64ffa45f33')
423 @decorators.skip_because(bug='2017110')
424 def test_update_backup(self):
425 """Update a backup"""
426 self._update_backup(expected_status=exceptions.Forbidden)
427
428
429 class ProjectMemberTests39(RbacV3BackupsTests39):
430 credentials = ['project_member', 'project_admin']
431
432 @classmethod
433 def setup_clients(cls):
434 super().setup_clients()
435 cls.client = cls.os_project_member.backups_client_latest
436
437 @decorators.idempotent_id('a1cdd6f2-e9bc-4f6a-a0e6-2493ac6f9f27')
438 def test_update_backup(self):
439 """Update a backup"""
440 self._update_backup(expected_status=200)
441
442
443 class ProjectAdminTests39(RbacV3BackupsTests39):
444 credentials = ['project_admin']
445
446 @classmethod
447 def setup_clients(cls):
448 super().setup_clients()
449 cls.client = cls.os_project_admin.backups_client_latest
450
451 @decorators.idempotent_id('2686eecf-e3cd-4f23-8771-aa040ed9be4b')
452 def test_update_backup(self):
453 """Update a backup"""
454 self._update_backup(expected_status=200)