Codebase list cinder-tempest-plugin / 842bcee
Merge tag '1.9.0' into debian/bobcat cinder-tempest-plugin 1.9.0 release meta:version: 1.9.0 meta:diff-start: - meta:series: bobcat meta:branch: master meta:release-type: release meta:pypi: no meta:first: yes meta:release:Author: Ghanshyam Mann <gmann@ghanshyammann.com> meta:release:Commit: Ghanshyam Mann <gmann@ghanshyammann.com> meta:release:Change-Id: Ia2974b50515a5880c484f8881105c192328e31e6 meta:release:Workflow+1: Thierry Carrez <thierry@openstack.org> meta:release:Code-Review+1: Luigi Toscano <ltoscano@redhat.com> meta:release:Code-Review+2: Thierry Carrez <thierry@openstack.org> meta:release:Code-Review+2: Elod Illes <elod.illes@est.tech> meta:release:Code-Review+1: Rajat Dhasmana <rajatdhasmana@gmail.com> Thomas Goirand 2 years ago
16 changed file(s) with 1605 addition(s) and 66 deletion(s). Raw diff Collapse all Expand all
1212 # do about this, which should be at the March 2023 virtual PTG.
1313 - cinder-tempest-plugin-lvm-tgt-barbican:
1414 voting: false
15 - cinder-tempest-plugin-lvm-lio-barbican-fips:
16 voting: false
1517 - nova-ceph-multistore:
1618 voting: false
1719 - cinder-tempest-plugin-cbak-ceph
2426 - cinder-tempest-plugin-basic-zed
2527 - cinder-tempest-plugin-basic-yoga
2628 - cinder-tempest-plugin-basic-xena
27 # Set this job to voting once we have some actual tests to run
28 - cinder-tempest-plugin-protection-functional:
29 voting: false
29 - cinder-tempest-plugin-protection-functional
3030 gate:
3131 jobs:
3232 - cinder-tempest-plugin-lvm-lio-barbican
7272 tempest_test_regex: '(^tempest\.(api|scenario)|(^cinder_tempest_plugin))'
7373 tempest_test_exclude_list: '{{ ansible_user_dir }}/{{ zuul.projects["opendev.org/openstack/tempest"].src_dir }}/tools/tempest-integrated-gate-storage-exclude-list.txt'
7474 # Temporarily exclude TestMultiAttachVolumeSwap until LP bug #1980816 is resolved.
75 tempest_exclude_regex: 'TestMultiAttachVolumeSwap'
75 # Other excluded tests are tests that are somewhat time consuming but unrelated
76 # to multi-attach testing.
77 tempest_exclude_regex: 'TestMultiAttachVolumeSwap|^tempest.api.image|^tempest.api.object_storage|^tempest.scenario.test_volume_boot_pattern.TestVolumeBootPattern.test_boot_server_from_encrypted|^tempest.scenario.test_server_advanced_ops|^tempest.scenario.test_unified_limits'
7678 tox_envlist: all
7779 devstack_localrc:
7880 ENABLE_VOLUME_MULTIATTACH: true
8284 - ^.*\.rst$
8385 - ^doc/.*$
8486 - ^releasenotes/.*$
87 timeout: 10800
8588
8689 - job:
8790 name: cinder-tempest-plugin-lvm-barbican-base-abstract
216219 volume_revert: True
217220 devstack_services:
218221 c-bak: true
222 devstack_localrc:
223 CINDER_QUOTA_VOLUMES: 25
224 timeout: 10800
219225
220226 - job:
221227 name: cinder-tempest-plugin-cbak-ceph-zed
278284 description: |
279285 This jobs configures Cinder with LVM, LIO, barbican and
280286 runs tempest tests and cinderlib tests on CentOS Stream 9.
287
288 - job:
289 name: cinder-tempest-plugin-lvm-lio-barbican-fips
290 parent: cinder-tempest-plugin-lvm-lio-barbican-centos-9-stream
291 description: |
292 This job configures Cinder with LVM, LIO, barbican and
293 runs tempest tests and cinderlib tests on CentOS Stream 9
294 under FIPS mode
295 pre-run: playbooks/enable-fips.yaml
296 vars:
297 configure_swap_size: 4096
298 nslookup_target: 'opendev.org'
299 tempest_exclude_regex: 'test_encrypted_cinder_volumes_cryptsetup'
281300
282301 - job:
283302 name: cinder-tempest-plugin-lvm-tgt-barbican
137137 'name',
138138 data_utils.rand_name(self.__class__.__name__ + '-instance'))
139139
140 if wait_until == 'SSHABLE' and not kwargs.get('validation_resources'):
141 kwargs['validation_resources'] = (
142 self.get_test_validation_resources(self.os_primary))
143 kwargs['validatable'] = True
144
140145 tenant_network = self.get_tenant_network()
141146 body, _ = compute.create_test_server(
142147 self.os_primary,
2929 super(VolumesBackupsTest, cls).skip_checks()
3030 if not CONF.volume_feature_enabled.backup:
3131 raise cls.skipException("Cinder backup feature disabled")
32
33 @classmethod
34 def setup_credentials(cls):
35 # Setting network=True, subnet=True creates a default network
36 cls.set_network_resources(
37 network=True,
38 subnet=True,
39 router=True,
40 dhcp=True)
41 super(VolumesBackupsTest, cls).setup_credentials()
3242
3343 @decorators.idempotent_id('885410c6-cd1d-452c-a409-7c32b7e0be15')
3444 def test_volume_snapshot_backup(self):
106116 server = self.create_server(
107117 name=server_name,
108118 block_device_mapping=bd_map,
109 wait_until='ACTIVE')
119 wait_until='SSHABLE')
110120
111121 # Delete VM
112122 self.os_primary.servers_client.delete_server(server['id'])
99 # License for the specific language governing permissions and limitations
1010 # under the License.
1111
12 from tempest.common import waiters
1213 from tempest import config
14 from tempest.lib.common import api_microversion_fixture
15 from tempest.lib.common import api_version_utils
16 from tempest.lib.common.utils import data_utils
17 from tempest.lib.common.utils import test_utils
18 from tempest.lib.decorators import cleanup_order
19 from tempest import test
1320
1421 CONF = config.CONF
1522
1623
17 class VolumeV3RbacBaseTests(object):
24 class VolumeV3RbacBaseTests(
25 api_version_utils.BaseMicroversionTest, test.BaseTestCase
26 ):
1827
1928 identity_version = 'v3'
2029
2736 "skipping RBAC tests. To enable these tests set "
2837 "`tempest.conf [enforce_scope] cinder=True`."
2938 )
39 if not CONF.service_available.cinder:
40 skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
41 raise cls.skipException(skip_msg)
42
43 api_version_utils.check_skip_with_microversion(
44 cls.min_microversion, cls.max_microversion,
45 CONF.volume.min_microversion, CONF.volume.max_microversion)
46
47 @classmethod
48 def setup_credentials(cls):
49 cls.set_network_resources()
50 super(VolumeV3RbacBaseTests, cls).setup_credentials()
51
52 def setUp(self):
53 super(VolumeV3RbacBaseTests, self).setUp()
54 self.useFixture(api_microversion_fixture.APIMicroversionFixture(
55 volume_microversion=self.request_microversion))
56
57 @classmethod
58 def resource_setup(cls):
59 super(VolumeV3RbacBaseTests, cls).resource_setup()
60 cls.request_microversion = (
61 api_version_utils.select_request_microversion(
62 cls.min_microversion,
63 CONF.volume.min_microversion))
3064
3165 def do_request(self, method, expected_status=200, client=None, **payload):
66 """Perform API call
67
68 Args:
69 method: Name of the API call
70 expected_status: HTTP desired response code
71 client: Client object if exists, None otherwise
72 payload: API call required parameters
73
74 Returns:
75 HTTP response
76 """
3277 if not client:
3378 client = self.client
3479 if isinstance(expected_status, type(Exception)):
3984 response = getattr(client, method)(**payload)
4085 self.assertEqual(response.response.status, expected_status)
4186 return response
87
88 @cleanup_order
89 def create_volume(self, client, **kwargs):
90 """Wrapper utility that returns a test volume
91
92 Args:
93 client: Client object
94
95 Returns:
96 ID of the created volume
97 """
98 kwargs['size'] = CONF.volume.volume_size
99 kwargs['name'] = data_utils.rand_name(
100 VolumeV3RbacBaseTests.__name__ + '-Volume'
101 )
102
103 volume_id = client.create_volume(**kwargs)['volume']['id']
104 self.cleanup(
105 test_utils.call_and_ignore_notfound_exc, func=self.delete_resource,
106 client=client, volume_id=volume_id
107 )
108 waiters.wait_for_volume_resource_status(
109 client=client, resource_id=volume_id, status='available'
110 )
111
112 return volume_id
113
114 @cleanup_order
115 def create_snapshot(self, client, volume_id, cleanup=True, **kwargs):
116 """Wrapper utility that returns a test snapshot.
117
118 Args:
119 client: Client object
120 volume_id: ID of the volume
121 cleanup: Boolean if should delete the snapshot
122
123 Returns:
124 ID of the created snapshot
125 """
126 kwargs['name'] = data_utils.rand_name(
127 VolumeV3RbacBaseTests.__name__ + '-Snapshot'
128 )
129
130 snapshot_id = client.create_snapshot(
131 volume_id=volume_id, **kwargs)['snapshot']['id']
132 if cleanup:
133 self.cleanup(
134 test_utils.call_and_ignore_notfound_exc,
135 func=self.delete_resource,
136 client=client, snapshot_id=snapshot_id
137 )
138 waiters.wait_for_volume_resource_status(
139 client=client, resource_id=snapshot_id, status='available'
140 )
141
142 return snapshot_id
143
144 @classmethod
145 def delete_resource(cls, client, **kwargs):
146 """Delete a resource by a given client
147
148 Args:
149 client: Client object
150
151 Keyword Args:
152 snapshot_id: ID of a snapshot
153 volume_id: ID of a volume
154 """
155 key, resource_id = list(kwargs.items())[0]
156 resource_name = key.split('_')[0]
157
158 del_action = getattr(client, f'delete_{resource_name}')
159 test_utils.call_and_ignore_notfound_exc(del_action, resource_id)
160 test_utils.call_and_ignore_notfound_exc(
161 client.wait_for_resource_deletion, resource_id)
99 # License for the specific language governing permissions and limitations
1010 # under the License.
1111
12 import abc
13
12 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
1413 from tempest.lib import decorators
1514 from tempest.lib import exceptions
1615
17 from cinder_tempest_plugin.api.volume import base
18 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
1916
20
21 class VolumeV3RbacCapabilityTests(rbac_base.VolumeV3RbacBaseTests,
22 metaclass=abc.ABCMeta):
17 class VolumeV3RbacCapabilityTests(rbac_base.VolumeV3RbacBaseTests):
2318
2419 @classmethod
2520 def setup_clients(cls):
3631 cls.admin_stats_client = (
3732 admin_client.volume_scheduler_stats_client_latest)
3833
39 @classmethod
40 def setup_credentials(cls):
41 super().setup_credentials()
42 cls.os_primary = getattr(cls, 'os_%s' % cls.credentials[0])
43
44 @abc.abstractmethod
45 def test_get_capabilities(self):
46 """Test volume_extension:capabilities policy.
47
48 This test must check:
49 * whether the persona can fetch capabilities for a host.
50
51 """
52 pass
34 def _get_capabilities(self, expected_status):
35 pools = self.admin_stats_client.list_pools()['pools']
36 host_name = pools[0]['name']
37 self.do_request(
38 'show_backend_capabilities',
39 expected_status=expected_status,
40 host=host_name
41 )
5342
5443
55 class ProjectAdminTests(VolumeV3RbacCapabilityTests, base.BaseVolumeTest):
44 class ProjectReaderTests(VolumeV3RbacCapabilityTests):
45 credentials = ['project_reader', 'project_admin', 'system_admin']
5646
47 @decorators.idempotent_id('d16034fc-4204-4ea8-94b3-714de59fdfbf')
48 def test_get_capabilities(self):
49 self._get_capabilities(expected_status=exceptions.Forbidden)
50
51
52 class ProjectMemberTests(VolumeV3RbacCapabilityTests):
53 credentials = ['project_member', 'project_admin', 'system_admin']
54
55 @decorators.idempotent_id('dbaf51de-fafa-4f55-875f-7537524489ab')
56 def test_get_capabilities(self):
57 self._get_capabilities(expected_status=exceptions.Forbidden)
58
59
60 class ProjectAdminTests(VolumeV3RbacCapabilityTests):
5761 credentials = ['project_admin', 'system_admin']
5862
5963 @decorators.idempotent_id('1fdbe493-e58f-48bf-bb38-52003eeef8cb')
6064 def test_get_capabilities(self):
61 pools = self.admin_stats_client.list_pools()['pools']
62 host_name = pools[0]['name']
63 self.do_request('show_backend_capabilities', expected_status=200,
64 host=host_name)
65
66
67 class ProjectMemberTests(ProjectAdminTests, base.BaseVolumeTest):
68
69 credentials = ['project_member', 'project_admin', 'system_admin']
70
71 @decorators.idempotent_id('dbaf51de-fafa-4f55-875f-7537524489ab')
72 def test_get_capabilities(self):
73 pools = self.admin_stats_client.list_pools()['pools']
74 host_name = pools[0]['name']
75 self.do_request('show_backend_capabilities',
76 expected_status=exceptions.Forbidden,
77 host=host_name)
78
79
80 class ProjectReaderTests(ProjectMemberTests, base.BaseVolumeTest):
81
82 credentials = ['project_reader', 'project_admin', 'system_admin']
83
84 @decorators.idempotent_id('d16034fc-4204-4ea8-94b3-714de59fdfbf')
85 def test_get_capabilities(self):
86 super().test_get_capabilities()
65 self._get_capabilities(expected_status=200)
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 tempest.common import waiters
13 from tempest import config
14 from tempest.lib.common.utils import data_utils
15 from tempest.lib.common.utils import test_utils
16 from tempest.lib import decorators
17 from tempest.lib import exceptions
18
19 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
20
21 CONF = config.CONF
22
23
24 class VolumeV3RbacSnapshotsTests(rbac_base.VolumeV3RbacBaseTests):
25
26 @classmethod
27 def setup_clients(cls):
28 super().setup_clients()
29 cls.vol_other_client = cls.os_project_admin.volumes_client_latest
30 cls.snap_other_client = cls.os_project_admin.snapshots_client_latest
31
32 def _list_snapshots(self, expected_status):
33 """Test list_snapshots operation
34
35 Args:
36 expected_status: The expected HTTP response code
37 """
38 volume_id = self.create_volume(client=self.vol_other_client)
39 self.create_snapshot(
40 client=self.snap_other_client, volume_id=volume_id
41 )
42 self.do_request(
43 expected_status=expected_status, method='list_snapshots'
44 )
45
46 def _show_snapshot(self, expected_status):
47 """Test show_snapshot operation
48
49 Args:
50 expected_status: The expected HTTP response code
51 """
52 volume_id = self.create_volume(client=self.vol_other_client)
53 snapshot_id = self.create_snapshot(
54 client=self.snap_other_client, volume_id=volume_id
55 )
56 self.do_request(
57 expected_status=expected_status, method='show_snapshot',
58 snapshot_id=snapshot_id
59 )
60
61 def _create_snapshot(self, expected_status):
62 """Test create_snapshot operation.
63
64 Args:
65 expected_status: The expected HTTP response code
66 """
67 volume_id = self.create_volume(client=self.vol_other_client)
68 snap_name = data_utils.rand_name(
69 self.__name__ + '-Snapshot'
70 )
71 if expected_status == 202:
72 snapshot_id = self.do_request(
73 method='create_snapshot', expected_status=202,
74 volume_id=volume_id, name=snap_name
75 )['snapshot']['id']
76 self.addCleanup(
77 test_utils.call_and_ignore_notfound_exc, self.delete_resource,
78 client=self.client, snapshot_id=snapshot_id
79 )
80 waiters.wait_for_volume_resource_status(
81 client=self.client, resource_id=snapshot_id, status='available'
82 )
83 elif expected_status == exceptions.Forbidden:
84 self.do_request(
85 method='create_snapshot', expected_status=expected_status,
86 volume_id=volume_id, name=snap_name
87 )
88
89 def _remove_snapshot(self, expected_status):
90 """Test create_snapshot operation.
91
92 Args:
93 expected_status: The expected HTTP response code
94 """
95 volume_id = self.create_volume(client=self.vol_other_client)
96 snapshot_id = self.create_snapshot(
97 client=self.snap_other_client, volume_id=volume_id
98 )
99
100 self.do_request(
101 method='delete_snapshot', snapshot_id=snapshot_id,
102 expected_status=expected_status
103 )
104 if expected_status == 202:
105 self.client.wait_for_resource_deletion(id=snapshot_id)
106
107 def _reset_snapshot_status(self, expected_status):
108 """Test reset_snapshot_status operation.
109
110 Args:
111 expected_status: The expected HTTP response code
112 """
113 volume_id = self.create_volume(client=self.vol_other_client)
114 snapshot_id = self.create_snapshot(
115 client=self.snap_other_client, volume_id=volume_id
116 )
117 self.do_request(
118 'reset_snapshot_status', expected_status=expected_status,
119 snapshot_id=snapshot_id, status='error'
120 )
121
122 def _update_snapshot(self, expected_status):
123 """Test update_snapshot operation.
124
125 Args:
126 expected_status: The expected HTTP response code
127 """
128 volume_id = self.create_volume(client=self.vol_other_client)
129 snapshot_id = self.create_snapshot(
130 client=self.snap_other_client, volume_id=volume_id
131 )
132 new_desc = self.__name__ + '-update_test'
133 self.do_request(
134 method='update_snapshot', expected_status=expected_status,
135 snapshot_id=snapshot_id, description=new_desc
136 )
137
138 def _update_snapshot_status(self, expected_status):
139 """Test update_snapshot_status operation.
140
141 Args:
142 expected_status: The expected HTTP response code
143 """
144 volume_id = self.create_volume(client=self.vol_other_client)
145 snapshot_id = self.create_snapshot(
146 client=self.snap_other_client, volume_id=volume_id
147 )
148
149 reset_status = 'creating' if expected_status == 202 else 'error'
150 request_status = 'error' if expected_status == 202 else 'creating'
151 self.os_project_admin.snapshots_client_latest.reset_snapshot_status(
152 snapshot_id=snapshot_id, status=reset_status
153 )
154 waiters.wait_for_volume_resource_status(
155 client=self.os_project_admin.snapshots_client_latest,
156 resource_id=snapshot_id, status=reset_status
157 )
158
159 self.do_request(
160 'update_snapshot_status', expected_status=expected_status,
161 snapshot_id=snapshot_id, status=request_status, progress='80%'
162 )
163
164 def _force_delete_snapshot(self, expected_status):
165 """Test force_delete_snapshot operation.
166
167 Args:
168 expected_status: The expected HTTP response code
169 """
170 volume_id = self.create_volume(client=self.vol_other_client)
171 snapshot_id = self.create_snapshot(
172 client=self.snap_other_client, volume_id=volume_id
173 )
174 self.do_request(
175 method='force_delete_snapshot', snapshot_id=snapshot_id,
176 expected_status=expected_status
177 )
178 if expected_status != exceptions.Forbidden:
179 self.client.wait_for_resource_deletion(id=snapshot_id)
180 waiters.wait_for_volume_resource_status(
181 client=self.os_project_admin.volumes_client_latest,
182 resource_id=volume_id, status='available'
183 )
184
185 def _unmanage_snapshot(self, expected_status):
186 """Test unmanage_snapshot operation.
187
188 Args:
189 expected_status: The expected HTTP response code
190 """
191 volume_id = self.create_volume(client=self.vol_other_client)
192 snapshot_id = self.create_snapshot(
193 client=self.snap_other_client, volume_id=volume_id
194 )
195 self.do_request(
196 method='unmanage_snapshot',
197 expected_status=expected_status, snapshot_id=snapshot_id
198 )
199 if expected_status != exceptions.Forbidden:
200 self.client.wait_for_resource_deletion(id=snapshot_id)
201
202 def _manage_snapshot(self, client, expected_status):
203 """Test reset_snapshot_status operation.
204
205 Args:
206 client: The client to perform the needed request
207 expected_status: The expected HTTP response code
208 """
209 # Create a volume
210 volume_id = self.create_volume(client=self.vol_other_client)
211
212 # Create a snapshot
213 snapshot_id = self.create_snapshot(
214 client=self.snap_other_client,
215 volume_id=volume_id,
216 cleanup=False
217 )
218 # Unmanage the snapshot
219 # Unmanage snapshot function works almost the same as delete snapshot,
220 # but it does not delete the snapshot data
221 self.snap_other_client.unmanage_snapshot(snapshot_id)
222 self.client.wait_for_resource_deletion(snapshot_id)
223
224 # Verify the original snapshot does not exist in snapshot list
225 params = {'all_tenants': 1}
226 all_snapshots = self.snap_other_client.list_snapshots(
227 detail=True, **params)['snapshots']
228 self.assertNotIn(snapshot_id, [v['id'] for v in all_snapshots])
229
230 # Manage the snapshot
231 name = data_utils.rand_name(
232 self.__class__.__name__ + '-Managed-Snapshot'
233 )
234 description = data_utils.rand_name(
235 self.__class__.__name__ + '-Managed-Snapshot-Description'
236 )
237 metadata = {"manage-snap-meta1": "value1",
238 "manage-snap-meta2": "value2",
239 "manage-snap-meta3": "value3"}
240 snapshot_ref = {
241 'volume_id': volume_id,
242 'ref': {CONF.volume.manage_snapshot_ref[0]:
243 CONF.volume.manage_snapshot_ref[1] % snapshot_id},
244 'name': name,
245 'description': description,
246 'metadata': metadata
247 }
248
249 new_snapshot = self.do_request(
250 client=client,
251 method='manage_snapshot', expected_status=expected_status,
252 volume_id=volume_id, ref=snapshot_ref
253 )
254 if expected_status != exceptions.Forbidden:
255 snapshot = new_snapshot['snapshot']
256 waiters.wait_for_volume_resource_status(
257 client=self.snap_other_client,
258 resource_id=snapshot['id'],
259 status='available'
260 )
261 self.delete_resource(
262 client=self.snap_other_client, snapshot_id=snapshot['id']
263 )
264
265
266 class ProjectReaderTests(VolumeV3RbacSnapshotsTests):
267
268 credentials = ['project_reader', 'project_admin']
269
270 @classmethod
271 def setup_clients(cls):
272 super().setup_clients()
273 cls.client = cls.os_project_reader.snapshots_client_latest
274
275 @decorators.idempotent_id('dd8e19dc-c8fd-443c-8aed-cdffe07fa6be')
276 def test_list_snapshots(self):
277 self._list_snapshots(expected_status=200)
278
279 @decorators.idempotent_id('6f69e8ed-4e11-40a1-9620-258cf3c45872')
280 def test_show_snapshot(self):
281 self._show_snapshot(expected_status=200)
282
283 @decorators.skip_because(bug="2017108")
284 @decorators.idempotent_id('13ae344f-fa01-44cc-b9f1-d04452940dc1')
285 def test_create_snapshot(self):
286 self._create_snapshot(expected_status=exceptions.Forbidden)
287
288 @decorators.skip_because(bug="2017108")
289 @decorators.idempotent_id('5b58f647-da0f-4d2a-bf68-680fc692efb4')
290 def test_delete_snapshot(self):
291 self._remove_snapshot(expected_status=exceptions.Forbidden)
292
293 @decorators.idempotent_id('809d8c8c-25bf-4f1f-9b77-1a81ce4292d1')
294 def test_reset_snapshot_status(self):
295 self._reset_snapshot_status(expected_status=exceptions.Forbidden)
296
297 @decorators.skip_because(bug="2017108")
298 @decorators.idempotent_id('c46f5df8-9a6f-4ed6-b94c-3b65ef05ee9e')
299 def test_update_snapshot(self):
300 self._update_snapshot(expected_status=exceptions.Forbidden)
301
302 @decorators.skip_because(bug="2017108")
303 @decorators.idempotent_id('c90f98d7-3665-4c9f-820f-3f4c2adfdbf5')
304 def test_update_snapshot_status(self):
305 self._update_snapshot_status(expected_status=exceptions.Forbidden)
306
307 @decorators.idempotent_id('63aa8184-897d-4e00-9b80-d2e7828f1b13')
308 def test_force_delete_snapshot(self):
309 self._force_delete_snapshot(expected_status=exceptions.Forbidden)
310
311 @decorators.idempotent_id('35495666-b663-4c68-ba44-0695e30a6838')
312 def test_unmanage_snapshot(self):
313 self._unmanage_snapshot(expected_status=exceptions.Forbidden)
314
315 @decorators.idempotent_id('d2d1326d-fb47-4448-a1e1-2d1219d30fd5')
316 def test_manage_snapshot(self):
317 self._manage_snapshot(
318 expected_status=exceptions.Forbidden,
319 client=self.os_project_reader.snapshot_manage_client_latest
320 )
321
322
323 class ProjectMemberTests(VolumeV3RbacSnapshotsTests):
324
325 credentials = ['project_member', 'project_admin']
326
327 @classmethod
328 def setup_clients(cls):
329 super().setup_clients()
330 cls.client = cls.os_project_member.snapshots_client_latest
331
332 @decorators.idempotent_id('5b3ec87f-443f-42f7-bd3c-ab05ea30c5e1')
333 def test_list_snapshots(self):
334 self._list_snapshots(expected_status=200)
335
336 @decorators.idempotent_id('6fee8967-951c-4957-b51b-97b83c13c7c3')
337 def test_show_snapshot(self):
338 self._show_snapshot(expected_status=200)
339
340 @decorators.idempotent_id('43f77b31-aab4-46d0-b76f-e17000d23589')
341 def test_create_snapshot(self):
342 self._create_snapshot(expected_status=202)
343
344 @decorators.idempotent_id('22939122-8b4e-47d5-abaa-774bc55c07fc')
345 def test_delete_snapshot(self):
346 self._remove_snapshot(expected_status=202)
347
348 @decorators.idempotent_id('da391afd-8baa-458b-b222-f6ab42ab47c3')
349 def test_reset_snapshot_status(self):
350 self._reset_snapshot_status(expected_status=exceptions.Forbidden)
351
352 @decorators.idempotent_id('a774bdca-bfbe-477d-9711-5fb64d7e34ea')
353 def test_update_snapshot(self):
354 self._update_snapshot(expected_status=200)
355
356 @decorators.idempotent_id('12e00e1b-bf84-41c1-8a1e-8625d1317789')
357 def test_update_snapshot_status(self):
358 self._update_snapshot_status(expected_status=202)
359
360 @decorators.idempotent_id('e7cb3eb0-d607-4c90-995d-df82d030eca8')
361 def test_force_delete_snapshot(self):
362 self._force_delete_snapshot(expected_status=exceptions.Forbidden)
363
364 @decorators.idempotent_id('dd7da3da-68ef-42f5-af1d-29803a4a04fd')
365 def test_unmanage_snapshot(self):
366 self._unmanage_snapshot(expected_status=exceptions.Forbidden)
367
368 @decorators.idempotent_id('c2501d05-9bca-42d7-9ab5-c0d9133e762f')
369 def test_manage_snapshot(self):
370 self._manage_snapshot(
371 expected_status=exceptions.Forbidden,
372 client=self.os_project_member.snapshot_manage_client_latest
373 )
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 tempest.common import waiters
13 from tempest import config
14 from tempest.lib.common.utils import data_utils
15 from tempest.lib.common.utils import test_utils
16 from tempest.lib import decorators
17 from tempest.lib import exceptions
18
19 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
20
21 CONF = config.CONF
22
23
24 class RbacV3UserMessagesTests(rbac_base.VolumeV3RbacBaseTests):
25 min_microversion = '3.3'
26
27 @classmethod
28 def setup_clients(cls):
29 super().setup_clients()
30 admin_client = cls.os_project_admin
31 cls.admin_messages_client = admin_client.volume_messages_client_latest
32 cls.admin_volumes_client = admin_client.volumes_client_latest
33 cls.admin_types_client = admin_client.volume_types_client_latest
34
35 def create_user_message(self):
36 """Trigger a 'no valid host' situation to generate a message."""
37 bad_protocol = data_utils.rand_name('storage_protocol')
38 bad_vendor = data_utils.rand_name('vendor_name')
39 extra_specs = {'storage_protocol': bad_protocol,
40 'vendor_name': bad_vendor}
41 vol_type_name = data_utils.rand_name(
42 self.__class__.__name__ + '-volume-type'
43 )
44 bogus_type = self.admin_types_client.create_volume_type(
45 name=vol_type_name, extra_specs=extra_specs
46 )['volume_type']
47 self.addCleanup(
48 self.admin_types_client.delete_volume_type, bogus_type['id']
49 )
50
51 params = {
52 'volume_type': bogus_type['id'], 'size': CONF.volume.volume_size
53 }
54 volume = self.admin_volumes_client.create_volume(**params)['volume']
55 waiters.wait_for_volume_resource_status(
56 self.admin_volumes_client, volume['id'], 'error'
57 )
58 self.addCleanup(
59 test_utils.call_and_ignore_notfound_exc,
60 self.admin_volumes_client.delete_volume,
61 volume['id']
62 )
63
64 messages = self.admin_messages_client.list_messages()['messages']
65 message_id = None
66 for message in messages:
67 if message['resource_uuid'] == volume['id']:
68 message_id = message['id']
69 break
70 self.assertIsNotNone(
71 message_id, f"No user message generated for volume {volume['id']}"
72 )
73 return message_id
74
75 def _list_messages(self, expected_status):
76 message_id = self.create_user_message()
77 self.addCleanup(
78 self.admin_messages_client.delete_message, message_id
79 )
80 self.do_request(
81 method='list_messages', expected_status=expected_status
82 )
83
84 def _show_message(self, expected_status):
85 message_id = self.create_user_message()
86 self.addCleanup(self.admin_messages_client.delete_message, message_id)
87 self.do_request(
88 method='show_message', expected_status=expected_status,
89 message_id=message_id
90 )
91
92 def _delete_message(self, expected_status):
93 message_id = self.create_user_message()
94 self.do_request(
95 method='delete_message', expected_status=expected_status,
96 message_id=message_id
97 )
98 if expected_status == exceptions.Forbidden:
99 self.addCleanup(
100 self.admin_messages_client.delete_message, message_id
101 )
102 else:
103 self.client.wait_for_resource_deletion(id=message_id)
104
105
106 class ProjectReaderTests(RbacV3UserMessagesTests):
107 credentials = ['project_reader', 'project_admin']
108
109 @classmethod
110 def setup_clients(cls):
111 super().setup_clients()
112 cls.client = cls.os_project_reader.volume_messages_client_latest
113
114 @decorators.idempotent_id('1bef8bf9-6457-40f8-ada2-bc4d27602a07')
115 def test_list_messages(self):
116 self._list_messages(expected_status=200)
117
118 @decorators.idempotent_id('689c53a9-6db9-44a8-9878-41d28899e0af')
119 def test_show_message(self):
120 self._show_message(expected_status=200)
121
122 @decorators.skip_because(bug='2009818')
123 @decorators.idempotent_id('c6e8744b-7749-425f-81b6-b1c3df6c7162')
124 def test_delete_message(self):
125 self._delete_message(expected_status=exceptions.Forbidden)
126
127
128 class ProjectMemberTests(RbacV3UserMessagesTests):
129 credentials = ['project_member', 'project_admin']
130
131 @classmethod
132 def setup_clients(cls):
133 super().setup_clients()
134 cls.client = cls.os_project_member.volume_messages_client_latest
135
136 @decorators.idempotent_id('fb470249-a482-49c6-84af-eda34891a714')
137 def test_list_messages(self):
138 self._list_messages(expected_status=200)
139
140 @decorators.idempotent_id('43d248ef-008d-4aff-8c7f-37959a0fa195')
141 def test_show_message(self):
142 self._show_message(expected_status=200)
143
144 @decorators.idempotent_id('a77cd089-cb74-4b44-abcb-06f1a6f80378')
145 def test_delete_message(self):
146 self._delete_message(expected_status=204)
147
148
149 class ProjectAdminTests(RbacV3UserMessagesTests):
150 credentials = ['project_admin']
151
152 @classmethod
153 def setup_clients(cls):
154 super().setup_clients()
155 cls.client = cls.os_project_admin.volume_messages_client_latest
156
157 @decorators.idempotent_id('f3567efc-863c-4668-8fb1-6aa3f836451d')
158 def test_list_messages(self):
159 self._list_messages(expected_status=200)
160
161 @decorators.idempotent_id('eecc7045-017b-492c-8594-2d40f5fda139')
162 def test_show_message(self):
163 self._show_message(expected_status=200)
164
165 @decorators.idempotent_id('1f2db6f2-148f-44c2-97ef-dcff0fccd49a')
166 def test_delete_message(self):
167 self._delete_message(expected_status=204)
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 tempest import config
13 from tempest.lib import decorators
14 from tempest.lib import exceptions
15
16 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
17
18 CONF = config.CONF
19
20
21 class VolumeV3RbacVolumeActionsTests(rbac_base.VolumeV3RbacBaseTests):
22
23 @classmethod
24 def setup_clients(cls):
25 super().setup_clients()
26 cls.vol_other_client = cls.os_project_admin.volumes_client_latest
27
28 def _extend_volume(self, expected_status):
29 """Test extend_volume operation.
30
31 Args:
32 expected_status: The expected HTTP response code
33 """
34 volume_id = self.create_volume(client=self.vol_other_client)
35 self.do_request(
36 method='extend_volume', volume_id=volume_id,
37 new_size=2, expected_status=expected_status
38 )
39
40 def _reset_volume_status(self, expected_status):
41 """Test reset_volume_status operation.
42
43 Args:
44 expected_status: The expected HTTP response code
45 """
46 volume_id = self.create_volume(client=self.vol_other_client)
47 self.do_request(
48 method='reset_volume_status', volume_id=volume_id,
49 status='error', expected_status=expected_status
50 )
51
52 def _retype_volume(self, expected_status):
53 """Test retype_volume operation.
54
55 Args:
56 expected_status: The expected HTTP response code
57 """
58 volume_id = self.create_volume(client=self.vol_other_client)
59 self.do_request(
60 method='retype_volume', volume_id=volume_id,
61 new_type='dedup-tier-replication', expected_status=expected_status
62 )
63
64 def _update_volume_readonly(self, expected_status):
65 """Test update_volume_readonly operation.
66
67 Args:
68 expected_status: The expected HTTP response code
69 """
70 volume_id = self.create_volume(client=self.vol_other_client)
71 self.do_request(
72 method='update_volume_readonly', volume_id=volume_id,
73 readonly=True, expected_status=expected_status
74 )
75
76 def _force_delete_volume(self, expected_status):
77 """Test force_delete_volume operation.
78
79 Args:
80 expected_status: The expected HTTP response code
81 """
82 volume_id = self.create_volume(client=self.vol_other_client)
83 self.do_request(
84 method='force_delete_volume', volume_id=volume_id,
85 expected_status=expected_status
86 )
87
88 def _reserve_volume(self, expected_status):
89 """Test reserve_volume operation.
90
91 Args:
92 expected_status: The expected HTTP response code
93 """
94 volume_id = self.create_volume(client=self.vol_other_client)
95 self.do_request(
96 method='reserve_volume', volume_id=volume_id,
97 expected_status=expected_status
98 )
99
100 def _unreserve_volume(self, expected_status):
101 """Test unreserve_volume operation.
102
103 Args:
104 expected_status: The expected HTTP response code
105 """
106 volume_id = self.create_volume(client=self.vol_other_client)
107 self.do_request(
108 method='unreserve_volume', volume_id=volume_id,
109 expected_status=expected_status
110 )
111
112
113 class ProjectReaderTests(VolumeV3RbacVolumeActionsTests):
114
115 credentials = ['project_reader', 'project_admin']
116
117 @classmethod
118 def setup_clients(cls):
119 super().setup_clients()
120 cls.client = cls.os_project_reader.volumes_client_latest
121
122 @decorators.skip_because(bug="2020261")
123 @decorators.idempotent_id('4d721c58-2f6f-4857-8f4f-0664d5f7bf49')
124 def test_extend_volume(self):
125 self._extend_volume(expected_status=exceptions.Forbidden)
126
127 @decorators.idempotent_id('434b454a-5cbe-492d-a416-70b8ff41f636')
128 def test_reset_volume_status(self):
129 self._reset_volume_status(expected_status=exceptions.Forbidden)
130
131 @decorators.skip_because(bug="2020261")
132 @decorators.idempotent_id('4675295a-7c72-4b04-8a43-03d7c88ab6bf')
133 def test_retype_volume(self):
134 self._retype_volume(expected_status=exceptions.Forbidden)
135
136 @decorators.skip_because(bug="2020261")
137 @decorators.idempotent_id('3beecd52-e314-40d8-875d-a0e7db8dd88f')
138 def test_update_volume_readonly(self):
139 self._update_volume_readonly(expected_status=exceptions.Forbidden)
140
141 @decorators.idempotent_id('b025ff12-73a4-4f15-af55-876cd43cade3')
142 def test_force_delete_volume(self):
143 self._force_delete_volume(expected_status=exceptions.Forbidden)
144
145 @decorators.skip_because(bug="2020261")
146 @decorators.idempotent_id('d2c13bf9-267a-4a71-be5c-391f22e9b433')
147 def test_reserve_volume(self):
148 self._reserve_volume(expected_status=exceptions.Forbidden)
149
150 @decorators.skip_because(bug="2020261")
151 @decorators.idempotent_id('725d85cf-96b2-4338-98f4-2f468099c4ed')
152 def test_unreserve_volume(self):
153 self._unreserve_volume(expected_status=exceptions.Forbidden)
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 tempest.lib.common.utils import data_utils
13 from tempest.lib import decorators
14 from tempest.lib import exceptions
15
16 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
17
18
19 class RbacV3VolumeTypesTests(rbac_base.VolumeV3RbacBaseTests):
20
21 min_microversion = '3.3'
22 extra_spec_key = 'key1'
23 encryption_type_key_cipher = 'cipher'
24 create_kwargs = {
25 'provider': 'LuksEncryptor',
26 'key_size': 256,
27 encryption_type_key_cipher: 'aes-xts-plain64',
28 'control_location': 'front-end'
29 }
30
31 @classmethod
32 def setup_clients(cls):
33 super().setup_clients()
34 admin_client = cls.os_project_admin
35 cls.admin_volumes_client = admin_client.volumes_client_latest
36 cls.admin_types_client = admin_client.volume_types_client_latest
37 cls.admin_encryption_types_client = \
38 admin_client.encryption_types_client_latest
39
40 @classmethod
41 def resource_setup(cls):
42 """Create a new volume-type for the test"""
43 super(RbacV3VolumeTypesTests, cls).resource_setup()
44 # create a volume type
45 cls.volume_type = cls.create_volume_type()
46
47 @classmethod
48 def create_volume_type(
49 cls, name=None, with_encryption=True, cleanup=True
50 ):
51 # create a volume type
52 if not name:
53 name = data_utils.rand_name("volume-type")
54 extra_specs = {cls.extra_spec_key: 'value1'}
55 params = {'name': name,
56 'description': "description",
57 'extra_specs': extra_specs,
58 'os-volume-type-access:is_public': True}
59 volume_type = cls.admin_types_client.create_volume_type(
60 **params
61 )['volume_type']
62
63 if with_encryption:
64 # Create encryption_type
65 cls.encryption_type = \
66 cls.admin_encryption_types_client.create_encryption_type(
67 volume_type['id'], **cls.create_kwargs)['encryption']
68
69 if cleanup:
70 cls.addClassResourceCleanup(
71 cls.admin_types_client.delete_volume_type, volume_type['id']
72 )
73
74 return volume_type
75
76 def _update_volume_type(self, expected_status):
77 """Update volume type"""
78 self.do_request(
79 method='update_volume_type',
80 expected_status=expected_status,
81 volume_type_id=self.volume_type['id'],
82 description='Updated volume type description'
83 )
84
85 def _create_or_update_extra_specs_for_volume_type(self, expected_status):
86 """Create or update extra specs"""
87 volume_type = self.create_volume_type(with_encryption=False)
88 # Create extra spec 'key2' with value 'value2'
89 extra_spec = {'key2': 'value2'}
90 self.do_request(
91 method='create_volume_type_extra_specs',
92 expected_status=expected_status,
93 volume_type_id=volume_type['id'],
94 extra_specs=extra_spec
95 )
96
97 # Update extra spec 'key2' with value 'updated value'
98 extra_spec = {'key2': 'updated value'}
99 self.do_request(
100 method='update_volume_type_extra_specs',
101 expected_status=expected_status,
102 volume_type_id=volume_type['id'],
103 extra_spec_name='key2',
104 extra_specs=extra_spec
105 )
106
107 def _list_all_extra_specs_for_volume_type(self, expected_status):
108 """List all extra_specs for a volume type"""
109 extra_specs = self.do_request(
110 method='list_volume_types_extra_specs',
111 expected_status=expected_status,
112 volume_type_id=self.volume_type['id']
113 )['extra_specs']
114 self.assertIn(
115 self.extra_spec_key,
116 list(extra_specs.keys()),
117 message=f"Key '{self.extra_spec_key}' not found in extra_specs."
118 )
119
120 def _show_extra_spec_for_volume_type(self, expected_status):
121 """Show extra_spec for a volume type"""
122 self.do_request(
123 method='show_volume_type_extra_specs',
124 expected_status=expected_status,
125 volume_type_id=self.volume_type['id'],
126 extra_specs_name=self.extra_spec_key
127 )
128
129 def _update_extra_spec_for_volume_type(self, expected_status):
130 """Update extra_spec for a volume type"""
131 spec_name = self.extra_spec_key
132 extra_spec = {spec_name: 'updated value'}
133 self.do_request(
134 method='update_volume_type_extra_specs',
135 expected_status=expected_status,
136 volume_type_id=self.volume_type['id'],
137 extra_spec_name=spec_name,
138 extra_specs=extra_spec
139 )
140
141 def _delete_extra_spec_for_volume_type(self, expected_status):
142 """Delete a volume type extra_spec"""
143 volume_type = self.create_volume_type(with_encryption=False)
144
145 self.do_request(
146 method='delete_volume_type_extra_specs',
147 expected_status=expected_status,
148 volume_type_id=volume_type['id'],
149 extra_spec_name=self.extra_spec_key
150 )
151
152 def _show_volume_type_detail(self, expected_status):
153 """Show volume type"""
154 self.do_request(
155 method='show_volume_type',
156 expected_status=expected_status,
157 volume_type_id=self.volume_type['id']
158 )
159
160 def _show_default_volume_type(self, expected_status):
161 """Show default volume type"""
162 self.do_request(
163 method='show_default_volume_type',
164 expected_status=expected_status
165 )
166
167 def _delete_volume_type(self, expected_status):
168 """Delete a volume type"""
169 cleanup = True if expected_status == exceptions.Forbidden\
170 else False
171 volume_type = self.create_volume_type(
172 with_encryption=False, cleanup=cleanup
173 )
174
175 self.do_request(
176 method='delete_volume_type',
177 expected_status=expected_status,
178 volume_type_id=volume_type['id']
179 )
180
181 def _list_volume_types(self, expected_status):
182 """List all volume types"""
183 self.do_request(
184 method='list_volume_types',
185 expected_status=expected_status
186 )
187
188 def _create_volume_type(self, expected_status):
189 """Create a volume type"""
190 volume_type = self.do_request(
191 method='create_volume_type',
192 expected_status=expected_status,
193 name="test-new-volume-type"
194 )
195 if expected_status != exceptions.Forbidden:
196 volume_type = volume_type['volume_type']
197 self.admin_types_client.delete_volume_type(
198 volume_type_id=volume_type['id']
199 )
200
201 def _show_encryption_type(self, expected_status):
202 """Show volume type's encryption type"""
203 self.do_request(
204 method='show_encryption_type',
205 expected_status=expected_status,
206 client=self.encryption_types_client,
207 volume_type_id=self.volume_type['id']
208 )
209
210 def _show_encryption_spec_item(self, expected_status):
211 """Show encryption spec item"""
212 self.do_request(
213 method='show_encryption_specs_item',
214 expected_status=expected_status,
215 client=self.encryption_types_client,
216 volume_type_id=self.volume_type['id'],
217 key=self.encryption_type_key_cipher
218 )
219
220 def _delete_encryption_type(self, expected_status):
221 """Delete encryption type"""
222 volume_type = self.create_volume_type(with_encryption=True)
223
224 self.do_request(
225 method='delete_encryption_type',
226 expected_status=expected_status,
227 client=self.encryption_types_client,
228 volume_type_id=volume_type['id']
229 )
230
231 def _create_encryption_type(self, expected_status):
232 """Create encryption type"""
233 volume_type = self.create_volume_type(with_encryption=False)
234
235 self.do_request(
236 method='create_encryption_type',
237 expected_status=expected_status,
238 client=self.encryption_types_client,
239 volume_type_id=volume_type['id'],
240 **self.create_kwargs
241 )
242
243 def _update_encryption_type(self, expected_status):
244 """Update encryption type"""
245 update_kwargs = {'key_size': 128}
246
247 self.do_request(
248 method='update_encryption_type',
249 expected_status=expected_status,
250 client=self.encryption_types_client,
251 volume_type_id=self.volume_type['id'],
252 **update_kwargs
253 )
254
255
256 class VolumeTypesReaderTests(RbacV3VolumeTypesTests):
257 """Test Volume types using 'reader' user"""
258 credentials = ['project_reader', 'project_admin']
259
260 @classmethod
261 def setup_clients(cls):
262 super().setup_clients()
263 cls.client = cls.os_project_reader.volume_types_client_latest
264 cls.encryption_types_client = \
265 cls.os_project_reader.encryption_types_client_latest
266
267 @decorators.idempotent_id('e3fdabf0-fd8c-4bab-9870-5a67fe25c6e4')
268 def test_update_volume_type(self):
269 self._update_volume_type(expected_status=exceptions.Forbidden)
270
271 @decorators.idempotent_id('b046a4d7-79a0-436b-9075-863e2299b73d')
272 def test_create_or_update_extra_specs_for_volume_type(self):
273 self._create_or_update_extra_specs_for_volume_type(
274 expected_status=exceptions.Forbidden
275 )
276
277 @decorators.skip_because(bug='2018467')
278 @decorators.idempotent_id('9499752c-3b27-41a3-8f55-4bdba7297f92')
279 def test_list_all_extra_specs_for_volume_type(self):
280 self._list_all_extra_specs_for_volume_type(
281 expected_status=200
282 )
283
284 @decorators.skip_because(bug='2018467')
285 @decorators.idempotent_id('a38f7248-3a5b-4e51-8e32-d2dcf9c771ea')
286 def test_show_extra_spec_for_volume_type(self):
287 self._show_extra_spec_for_volume_type(expected_status=200)
288
289 @decorators.idempotent_id('68689644-22a8-4ba6-a642-db4258681586')
290 def test_update_extra_spec_for_volume_type(self):
291 self._update_extra_spec_for_volume_type(
292 expected_status=exceptions.Forbidden
293 )
294
295 @decorators.idempotent_id('a7cdd9ae-f389-48f6-b144-abf336b1637b')
296 def test_delete_extra_spec_for_volume_type(self):
297 self._delete_extra_spec_for_volume_type(
298 expected_status=exceptions.Forbidden
299 )
300
301 @decorators.skip_because(bug='2016402')
302 @decorators.idempotent_id('7ea28fc2-ce5a-48c9-8d03-31c2826fe566')
303 def test_show_volume_type_detail(self):
304 self._show_volume_type_detail(expected_status=200)
305
306 @decorators.skip_because(bug='2016402')
307 @decorators.idempotent_id('aceab52a-c503-4081-936e-b9df1c31046d')
308 def test_show_default_volume_type(self):
309 self._show_default_volume_type(expected_status=200)
310
311 @decorators.idempotent_id('35581811-6288-4698-aaaf-7f5a4fe662e8')
312 def test_delete_volume_type(self):
313 self._delete_volume_type(expected_status=exceptions.Forbidden)
314
315 @decorators.skip_because(bug='2016402')
316 @decorators.idempotent_id('e8a438f9-e9c1-4f3f-8ae3-ad80ee02cd6a')
317 def test_list_volume_types(self):
318 self._list_volume_types(expected_status=200)
319
320 @decorators.idempotent_id('3c3a39b1-fff5-492b-8c1c-9520063901ef')
321 def test_create_volume_type(self):
322 self._create_volume_type(expected_status=exceptions.Forbidden)
323
324 @decorators.idempotent_id('84bd20f1-621c-416d-add2-fbae57137239')
325 def test_show_encryption_type(self):
326 self._show_encryption_type(expected_status=exceptions.Forbidden)
327
328 @decorators.idempotent_id('ab9c7149-fab7-4584-b4ff-8b997cd62e75')
329 def test_show_encryption_spec_item(self):
330 self._show_encryption_spec_item(expected_status=exceptions.Forbidden)
331
332 @decorators.idempotent_id('8d85ec39-bc32-4f49-88e6-63adc7e1f832')
333 def test_delete_encryption_type(self):
334 self._delete_encryption_type(expected_status=exceptions.Forbidden)
335
336 @decorators.idempotent_id('c7c0892e-08d1-45e0-8ebf-be949cb4ab02')
337 def test_create_encryption_type(self):
338 self._create_encryption_type(expected_status=exceptions.Forbidden)
339
340 @decorators.idempotent_id('8186d5bc-183a-4fcc-9c6a-e2b247a0caee')
341 def test_update_encryption_type(self):
342 self._update_encryption_type(expected_status=exceptions.Forbidden)
343
344
345 class VolumeTypesMemberTests(RbacV3VolumeTypesTests):
346 """Test Volume types using 'member' user"""
347 credentials = ['project_member', 'project_admin']
348
349 @classmethod
350 def setup_clients(cls):
351 super().setup_clients()
352 cls.client = cls.os_project_member.volume_types_client_latest
353 cls.encryption_types_client = \
354 cls.os_project_member.encryption_types_client_latest
355
356 @decorators.idempotent_id('e5e642bf-2f31-4d04-ad43-6ad75562b7e4')
357 def test_update_volume_type(self):
358 self._update_volume_type(expected_status=exceptions.Forbidden)
359
360 @decorators.idempotent_id('fda21e7e-9292-49b8-9754-f3c25b8e5f57')
361 def test_create_or_update_extra_specs_for_volume_type(self):
362 self._create_or_update_extra_specs_for_volume_type(
363 expected_status=exceptions.Forbidden
364 )
365
366 @decorators.skip_because(bug='2018467')
367 @decorators.idempotent_id('82fd0d34-17b3-4f45-bd2e-728c9a8bff8c')
368 def test_list_all_extra_specs_for_volume_type(self):
369 self._list_all_extra_specs_for_volume_type(
370 expected_status=200
371 )
372
373 @decorators.skip_because(bug='2018467')
374 @decorators.idempotent_id('67aa0b40-7c0a-4ae7-8682-fb4f20abd390')
375 def test_show_extra_spec_for_volume_type(self):
376 self._show_extra_spec_for_volume_type(expected_status=200)
377
378 @decorators.idempotent_id('65470a71-254d-4152-bdaa-6b7f43e9c74f')
379 def test_update_extra_spec_for_volume_type(self):
380 self._update_extra_spec_for_volume_type(
381 expected_status=exceptions.Forbidden
382 )
383
384 @decorators.idempotent_id('3695be33-bd22-4090-8252-9c42eb7eeef6')
385 def test_delete_extra_spec_for_volume_type(self):
386 self._delete_extra_spec_for_volume_type(
387 expected_status=exceptions.Forbidden
388 )
389
390 @decorators.idempotent_id('319f3ca1-bdd7-433c-9bed-03c7b093e7a2')
391 def test_show_volume_type_detail(self):
392 self._show_volume_type_detail(expected_status=200)
393
394 @decorators.skip_because(bug='2016402')
395 @decorators.idempotent_id('2e990c61-a2ea-4a01-a2dc-1f483c934e8d')
396 def test_show_default_volume_type(self):
397 self._show_default_volume_type(expected_status=200)
398
399 @decorators.idempotent_id('6847c211-647b-4d02-910c-773e76b99fcd')
400 def test_delete_volume_type(self):
401 self._delete_volume_type(expected_status=exceptions.Forbidden)
402
403 @decorators.idempotent_id('308f80c9-6342-45a1-8e6e-9e400b510013')
404 def test_list_volume_types(self):
405 self._list_volume_types(expected_status=200)
406
407 @decorators.idempotent_id('81cebbb8-fa0d-4bd8-a433-e43c7b187456')
408 def test_create_volume_type(self):
409 self._create_volume_type(expected_status=exceptions.Forbidden)
410
411 @decorators.idempotent_id('7c84b013-c5a8-434f-8ea7-23c5b2d46d5e')
412 def test_show_encryption_type(self):
413 self._show_encryption_type(expected_status=exceptions.Forbidden)
414
415 @decorators.idempotent_id('387974ce-3544-48e3-81c0-3f86a5b60b93')
416 def test_show_encryption_spec_item(self):
417 self._show_encryption_spec_item(expected_status=exceptions.Forbidden)
418
419 @decorators.idempotent_id('c0163522-524f-4dfb-a3d4-6648f58ce99c')
420 def test_delete_encryption_type(self):
421 self._delete_encryption_type(expected_status=exceptions.Forbidden)
422
423 @decorators.idempotent_id('65d86181-905a-4aa6-a9e5-672415d819a0')
424 def test_create_encryption_type(self):
425 self._create_encryption_type(expected_status=exceptions.Forbidden)
426
427 @decorators.idempotent_id('2633f1d3-e648-4d12-86b9-e7f72b41ec68')
428 def test_update_encryption_type(self):
429 self._update_encryption_type(expected_status=exceptions.Forbidden)
430
431
432 class VolumeTypesAdminTests(RbacV3VolumeTypesTests):
433 """Test Volume types using 'admin' user"""
434 credentials = ['project_admin']
435
436 @classmethod
437 def setup_clients(cls):
438 super().setup_clients()
439 cls.client = cls.os_project_admin.volume_types_client_latest
440 cls.encryption_types_client = \
441 cls.os_project_admin.encryption_types_client_latest
442
443 @decorators.idempotent_id('77d065ef-ffdd-4749-b326-d64fbf5d0432')
444 def test_update_volume_type(self):
445 self._update_volume_type(expected_status=200)
446
447 @decorators.idempotent_id('422271a7-0128-4fd6-9f60-aeb4a1ce16ea')
448 def test_create_or_update_extra_specs_for_volume_type(self):
449 self._create_or_update_extra_specs_for_volume_type(
450 expected_status=200
451 )
452
453 @decorators.idempotent_id('5c491d13-df15-4721-812e-2ed473b86a12')
454 def test_list_all_extra_specs_for_volume_type(self):
455 self._list_all_extra_specs_for_volume_type(
456 expected_status=200
457 )
458
459 @decorators.skip_because(bug='2018467')
460 @decorators.idempotent_id('a2cca7b6-0af9-47e5-b8c1-4e0f01822d4e')
461 def test_show_extra_spec_for_volume_type(self):
462 self._show_extra_spec_for_volume_type(expected_status=200)
463
464 @decorators.idempotent_id('d0ff17d3-2c47-485f-b2f1-d53ec32c32e2')
465 def test_update_extra_spec_for_volume_type(self):
466 self._update_extra_spec_for_volume_type(
467 expected_status=200
468 )
469
470 @decorators.idempotent_id('4661cc2f-8727-4998-a427-8cb1d512b68a')
471 def test_delete_extra_spec_for_volume_type(self):
472 self._delete_extra_spec_for_volume_type(
473 expected_status=202
474 )
475
476 @decorators.idempotent_id('7f794e33-b5cf-4172-b39e-a56cd9c18a2e')
477 def test_show_volume_type_detail(self):
478 self._show_volume_type_detail(expected_status=200)
479
480 @decorators.skip_because(bug='2016402')
481 @decorators.idempotent_id('93886ad8-5cd0-4def-8b0e-40418e55050d')
482 def test_show_default_volume_type(self):
483 self._show_default_volume_type(expected_status=200)
484
485 @decorators.idempotent_id('7486259d-5c40-4fb3-8a95-491c45a0a872')
486 def test_delete_volume_type(self):
487 self._delete_volume_type(expected_status=202)
488
489 @decorators.idempotent_id('e075e8ff-bb05-4c84-b2ab-0205ef3e8dbd')
490 def test_list_volume_types(self):
491 self._list_volume_types(expected_status=200)
492
493 @decorators.idempotent_id('57384db2-9408-4a31-8c15-022eea5f9b76')
494 def test_create_volume_type(self):
495 self._create_volume_type(expected_status=200)
496
497 @decorators.idempotent_id('46fc49a3-f76f-4c22-ac83-8d1665437810')
498 def test_show_encryption_type(self):
499 self._show_encryption_type(expected_status=200)
500
501 @decorators.idempotent_id('4ff57649-bfe1-48f4-aaac-4577affba8d7')
502 def test_show_encryption_spec_item(self):
503 self._show_encryption_spec_item(expected_status=200)
504
505 @decorators.idempotent_id('e622af7d-a412-4903-9256-256d8e3cc560')
506 def test_delete_encryption_type(self):
507 self._delete_encryption_type(expected_status=202)
508
509 @decorators.idempotent_id('e7c4e925-6ce6-439b-8be8-6df4cbc32cdc')
510 def test_create_encryption_type(self):
511 self._create_encryption_type(expected_status=200)
512
513 @decorators.idempotent_id('90beb71d-93fa-4252-8566-192bdd517715')
514 def test_update_encryption_type(self):
515 self._update_encryption_type(expected_status=200)
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 tempest import config
13 from tempest.lib import decorators
14 from tempest.lib import exceptions
15
16 from cinder_tempest_plugin.rbac.v3 import base as rbac_base
17
18 CONF = config.CONF
19
20
21 class VolumeV3RbacVolumesTests(rbac_base.VolumeV3RbacBaseTests):
22
23 min_microversion = '3.12'
24
25 @classmethod
26 def setup_clients(cls):
27 super().setup_clients()
28 cls.vol_other_client = cls.os_project_admin.volumes_client_latest
29
30 def _create_volume(self, expected_status, **kwargs):
31 """Test create_volume operation.
32
33 Args:
34 expected_status: The expected HTTP response code
35 """
36 kwargs['size'] = CONF.volume.volume_size
37 self.do_request(
38 method='create_volume', expected_status=expected_status, **kwargs
39 )
40
41 def _show_volume(self, expected_status):
42 """Test show_volume operation
43
44 Args:
45 expected_status: The expected HTTP response code
46 """
47 volume_id = self.create_volume(client=self.vol_other_client)
48 self.do_request(
49 method='show_volume', volume_id=volume_id,
50 expected_status=expected_status
51 )
52
53 def _list_volumes(self, expected_status):
54 """Test list_volumes operation
55
56 Args:
57 expected_status: The expected HTTP response code
58 """
59 self.create_volume(client=self.vol_other_client)
60 self.do_request(method='list_volumes', expected_status=expected_status)
61
62 def _list_volumes_detail(self, expected_status):
63 """Test list_volumes details operation
64
65 Args:
66 expected_status: The expected HTTP response code
67 """
68 self.create_volume(client=self.vol_other_client)
69 self.do_request(
70 method='list_volumes', detail=True, expected_status=expected_status
71 )
72
73 def _show_volume_summary(self, expected_status):
74 """Test show_volume_summary operation
75
76 Args:
77 expected_status: The expected HTTP response code
78 """
79 self.create_volume(client=self.vol_other_client)
80 self.do_request(
81 method='show_volume_summary', expected_status=expected_status
82 )
83
84 def _update_volume(self, expected_status):
85 """Test update_volume operation.
86
87 Args:
88 expected_status: The expected HTTP response code
89 """
90 volume_id = self.create_volume(client=self.vol_other_client)
91 new_desc = self.__name__ + '-update_test'
92 self.do_request(
93 method='update_volume', volume_id=volume_id, description=new_desc,
94 expected_status=expected_status
95 )
96
97 def _set_bootable_volume(self, expected_status):
98 """Test set_bootable_volume operation.
99
100 Args:
101 expected_status: The expected HTTP response code
102 """
103 volume_id = self.create_volume(client=self.vol_other_client)
104 self.do_request(
105 method='set_bootable_volume', volume_id=volume_id,
106 bootable=True, expected_status=expected_status
107 )
108
109 def _delete_volume(self, expected_status):
110 """Test delete_volume operation.
111
112 Args:
113 expected_status: The expected HTTP response code
114 """
115 volume_id = self.create_volume(client=self.vol_other_client)
116 self.do_request(
117 method='delete_volume', volume_id=volume_id,
118 expected_status=expected_status
119 )
120
121
122 class ProjectReaderTests(VolumeV3RbacVolumesTests):
123
124 credentials = ['project_reader', 'project_admin']
125
126 @classmethod
127 def setup_clients(cls):
128 super().setup_clients()
129 cls.client = cls.os_project_reader.volumes_client_latest
130
131 @decorators.skip_because(bug="2020113")
132 @decorators.idempotent_id('3d87f960-6210-45f5-b70b-679d67a4e17e')
133 def test_create_volume(self):
134 self._create_volume(expected_status=exceptions.Forbidden)
135
136 @decorators.idempotent_id('9b2667f2-744e-4d1f-8c39-17060010f19f')
137 def test_show_volume(self):
138 self._show_volume(expected_status=200)
139
140 @decorators.idempotent_id('2f4da8f9-cdc5-4a6e-9143-8237634a629c')
141 def test_list_volumes(self):
142 self._list_volumes(expected_status=200)
143
144 @decorators.idempotent_id('b11e59cd-d1dd-43e4-9676-22ab394f5d18')
145 def test_list_volumes_detail(self):
146 self._list_volumes_detail(expected_status=200)
147
148 @decorators.idempotent_id('ef347930-54dc-432f-b742-0a060fc37ae8')
149 def test_show_volume_summary(self):
150 self._show_volume_summary(expected_status=200)
151
152 @decorators.skip_because(bug="2020113")
153 @decorators.idempotent_id('cda92972-7213-4fa0-bc14-ab012dc95931')
154 def test_update_volume(self):
155 self._update_volume(expected_status=exceptions.Forbidden)
156
157 @decorators.skip_because(bug="2020113")
158 @decorators.idempotent_id('9970b57d-8d5d-460e-931b-28a112df81e0')
159 def test_set_bootable_volume(self):
160 self._set_bootable_volume(expected_status=exceptions.Forbidden)
161
162 @decorators.skip_because(bug="2020113")
163 @decorators.idempotent_id('4fd4dce8-ed8a-4f05-8aac-da99858b563d')
164 def test_delete_volume(self):
165 self._delete_volume(expected_status=exceptions.Forbidden)
2222
2323 def setUp(self):
2424 super(SnapshotDataIntegrityTests, self).setUp()
25 self.keypair = self.create_keypair()
25 self.validation_resources = self.get_test_validation_resources(
26 self.os_primary)
27 # NOTE(danms): If validation is enabled, we will have a keypair to use,
28 # otherwise we need to create our own.
29 if 'keypair' in self.validation_resources:
30 self.keypair = self.validation_resources['keypair']
31 else:
32 self.keypair = self.create_keypair()
2633 self.security_group = self.create_security_group()
2734
2835 @decorators.idempotent_id('ff10644e-5a70-4a9f-9801-8204bb81fb61')
4754 # Create an instance
4855 server = self.create_server(
4956 key_name=self.keypair['name'],
57 validatable=True,
58 validation_resources=self.validation_resources,
59 wait_until='SSHABLE',
5060 security_groups=[{'name': self.security_group['name']}])
5161
5262 # Create an empty volume
3636 @classmethod
3737 def resource_cleanup(cls):
3838 super(TestEncryptedCinderVolumes, cls).resource_cleanup()
39
40 def launch_instance(self):
41 keypair = self.create_keypair()
42
43 return self.create_server(key_name=keypair['name'])
4439
4540 def attach_detach_volume(self, server, volume):
4641 attached_volume = self.nova_volume_attach(server, volume)
107102 self.volumes_client, volume_s['id'], 'available')
108103 volume_source = self.volumes_client.show_volume(
109104 volume_s['id'])['volume']
110 server = self.launch_instance()
105 validation_resources = self.get_test_validation_resources(
106 self.os_primary)
107 server = self.create_server(wait_until='SSHABLE',
108 validatable=True,
109 validation_resources=validation_resources)
111110 self.attach_detach_volume(server, volume_source)
112111
113112 @decorators.idempotent_id('5bb622ab-5060-48a8-8840-d589a548b7e4')
121120 * Create an encrypted volume from image
122121 * Boot an instance from the volume
123122 * Write data to the volume
124 * Detach volume
125 * Create a clone from the first volume
126 * Create another encrypted volume from source_volumeid
123 * Destroy the instance
124 * Create a clone of the encrypted volume
127125 * Boot an instance from cloned volume
128126 * Verify the data
129127 """
3030
3131 def setUp(self):
3232 super(VolumeMultiattachTests, self).setUp()
33 self.keypair = self.create_keypair()
33 self.validation_resources = self.get_test_validation_resources(
34 self.os_primary)
35 # NOTE(danms): If validation is enabled, we will have a keypair to use,
36 # otherwise we need to create our own.
37 if 'keypair' in self.validation_resources:
38 self.keypair = self.validation_resources['keypair']
39 else:
40 self.keypair = self.create_keypair()
3441 self.security_group = self.create_security_group()
3542
3643 @classmethod
5158 # Create an instance
5259 server_1 = self.create_server(
5360 key_name=self.keypair['name'],
61 wait_until='SSHABLE',
62 validatable=True,
63 validation_resources=self.validation_resources,
5464 security_groups=[{'name': self.security_group['name']}])
5565
5666 # Create multiattach type
91101 # Create another instance
92102 server_2 = self.create_server(
93103 key_name=self.keypair['name'],
104 validatable=True,
105 validation_resources=self.validation_resources,
106 wait_until='SSHABLE',
94107 security_groups=[{'name': self.security_group['name']}])
95108
96109 instance_2_ip = self.get_server_ip(server_2)
116129 # Create an instance
117130 server = self.create_server(
118131 key_name=self.keypair['name'],
132 validatable=True,
133 validation_resources=self.validation_resources,
134 wait_until='SSHABLE',
119135 security_groups=[{'name': self.security_group['name']}])
120136
121137 # Create multiattach type
0 - hosts: all
1 roles:
2 - enable-fips
44 pbr!=2.1.0,>=2.0.0 # Apache-2.0
55 oslo.config>=5.1.0 # Apache-2.0
66 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
7 tempest>=27.0.0 # Apache-2.0
7 tempest>=34.2.0 # Apache-2.0
1818 Programming Language :: Python :: 3.7
1919 Programming Language :: Python :: 3.8
2020 Programming Language :: Python :: 3.9
21 Programming Language :: Python :: 3.10
2122
2223 [files]
2324 packages =