Codebase list cinder-tempest-plugin / d8e875b
Merge tag '1.14.0' into debian/dalmatian cinder-tempest-plugin 1.14.0 release meta:version: 1.14.0 meta:diff-start: - meta:series: dalmatian meta:branch: master meta:release-type: release meta:pypi: no meta:first: no meta:release:Author: Brian Rosmaita <rosmaita.fossdev@gmail.com> meta:release:Commit: Brian Rosmaita <rosmaita.fossdev@gmail.com> meta:release:Change-Id: I81a91c3ca656f9cd4abf8360726bf65e2991f3f4 meta:release:Workflow+1: Elod Illes <elod.illes@est.tech> meta:release:Code-Review+2: Jens Harbott <frickler@offenerstapel.de> meta:release:Code-Review+2: Elod Illes <elod.illes@est.tech> meta:release:Code-Review+1: Jon Bernard <jobernar@redhat.com> Thomas Goirand 1 year, 8 months ago
8 changed file(s) with 215 addition(s) and 47 deletion(s). Raw diff Collapse all Expand all
2020 - cinder-tempest-plugin-cbak-ceph
2121 - cinder-tempest-plugin-cbak-s3
2222 # As per the Tempest "Stable Branch Support Policy", Tempest will only
23 # support the "Maintained" stable branches and not the "Extended Maintained"
24 # branches. That is what we need to do for all tempest plugins. Only jobs
25 # for the current releasable ("Maintained") stable branches should be listed
26 # here.
23 # support the "Maintained" stable branches, so only jobs for the
24 # current stable branches should be listed here.
25 - cinder-tempest-plugin-basic-2024-1
2726 - cinder-tempest-plugin-basic-2023-2
2827 - cinder-tempest-plugin-basic-2023-1
29 - cinder-tempest-plugin-basic-zed
3028 - cinder-tempest-plugin-protection-functional
3129 gate:
3230 jobs:
3735 - cinder-tempest-plugin-cbak-ceph
3836 experimental:
3937 jobs:
38 - cinder-tempest-plugin-cbak-ceph-2024-1
4039 - cinder-tempest-plugin-cbak-ceph-2023-2
4140 - cinder-tempest-plugin-cbak-ceph-2023-1
42 - cinder-tempest-plugin-cbak-ceph-zed
4341
4442 - job:
4543 name: cinder-tempest-plugin-protection-functional
268266 timeout: 10800
269267
270268 - job:
269 name: cinder-tempest-plugin-cbak-ceph-2024-1
270 parent: cinder-tempest-plugin-cbak-ceph
271 nodeset: openstack-single-node-jammy
272 override-checkout: stable/2024.1
273
274 - job:
271275 name: cinder-tempest-plugin-cbak-ceph-2023-2
272276 parent: cinder-tempest-plugin-cbak-ceph
273277 nodeset: openstack-single-node-jammy
278282 parent: cinder-tempest-plugin-cbak-ceph
279283 nodeset: openstack-single-node-jammy
280284 override-checkout: stable/2023.1
281
282 - job:
283 name: cinder-tempest-plugin-cbak-ceph-zed
284 parent: cinder-tempest-plugin-cbak-ceph
285 nodeset: openstack-single-node-focal
286 override-checkout: stable/zed
287285
288286 # variant for pre-Ussuri branches (no volume revert for Ceph),
289287 # should this job be used on those branches
415413 - ^releasenotes/.*$
416414
417415 - job:
416 name: cinder-tempest-plugin-basic-2024-1
417 parent: cinder-tempest-plugin-basic
418 nodeset: openstack-single-node-jammy
419 override-checkout: stable/2024.1
420
421 - job:
418422 name: cinder-tempest-plugin-basic-2023-2
419423 parent: cinder-tempest-plugin-basic
420424 nodeset: openstack-single-node-jammy
425429 parent: cinder-tempest-plugin-basic
426430 nodeset: openstack-single-node-jammy
427431 override-checkout: stable/2023.1
428
429 - job:
430 name: cinder-tempest-plugin-basic-zed
431 parent: cinder-tempest-plugin-basic
432 nodeset: openstack-single-node-focal
433 override-checkout: stable/zed
1212 # License for the specific language governing permissions and limitations
1313 # under the License.
1414
15 import io
16
1517 from tempest.common import compute
1618 from tempest.common import waiters
1719 from tempest import config
156158 self.os_primary.servers_client.delete_server,
157159 body['id'])
158160 return body
161
162 @classmethod
163 def create_image_with_data(cls, **kwargs):
164 # we do this as a class method so we can use the
165 # addClassResourceCleanup functionality of tempest.test.BaseTestCase
166 images_client = cls.os_primary.image_client_v2
167 if 'min_disk' not in kwargs:
168 kwargs['min_disk'] = 1
169 response = images_client.create_image(**kwargs)
170 image_id = response['id']
171 cls.addClassResourceCleanup(
172 images_client.wait_for_resource_deletion, image_id)
173 cls.addClassResourceCleanup(
174 test_utils.call_and_ignore_notfound_exc,
175 images_client.delete_image, image_id)
176
177 # upload "data" to image
178 image_file = io.BytesIO(data_utils.random_bytes(size=1024))
179 images_client.store_image_file(image_id, image_file)
180
181 waiters.wait_for_image_status(images_client, image_id, 'active')
182 image = images_client.show_image(image_id)
183 return image
159184
160185
161186 class BaseVolumeAdminTest(BaseVolumeTest):
99 # License for the specific language governing permissions and limitations
1010 # under the License.
1111
12 import io
13
14 from tempest.common import waiters
1512 from tempest import config
16 from tempest.lib.common.utils import data_utils
17 from tempest.lib.common.utils import test_utils
1813 from tempest.lib import decorators
1914
2015 from cinder_tempest_plugin.api.volume import base
3025 super(VolumeAndVolumeTypeFromImageTest, cls).skip_checks()
3126 if not CONF.service_available.glance:
3227 raise cls.skipException("Glance service is disabled")
33
34 @classmethod
35 def create_image_with_data(cls, **kwargs):
36 # we do this as a class method so we can use the
37 # addClassResourceCleanup functionality of tempest.test.BaseTestCase
38 images_client = cls.os_primary.image_client_v2
39 if 'min_disk' not in kwargs:
40 kwargs['min_disk'] = 1
41 response = images_client.create_image(**kwargs)
42 image_id = response['id']
43 cls.addClassResourceCleanup(
44 images_client.wait_for_resource_deletion, image_id)
45 cls.addClassResourceCleanup(
46 test_utils.call_and_ignore_notfound_exc,
47 images_client.delete_image, image_id)
48
49 # upload "data" to image
50 image_file = io.BytesIO(data_utils.random_bytes(size=1024))
51 images_client.store_image_file(image_id, image_file)
52
53 waiters.wait_for_image_status(images_client, image_id, 'active')
54 image = images_client.show_image(image_id)
55 return image
5628
5729 @decorators.idempotent_id('6e9266ff-a917-4dd5-aa4a-c36e59e7a2a6')
5830 def test_create_from_image_with_volume_type_image_property(self):
1212 # License for the specific language governing permissions and limitations
1313 # under the License.
1414
15
16 from tempest.common import utils
17 from tempest.common import waiters
1518 from tempest import config
1619 from tempest.lib import decorators
20 import testtools
1721
1822 from cinder_tempest_plugin.api.volume import base
1923
118122 self._delete_vol_and_wait(volume_1)
119123 self._delete_vol_and_wait(volume_2)
120124 self._delete_vol_and_wait(volume_3)
125
126
127 class VolumeImageDependencyTests(base.BaseVolumeTest):
128 """Volume<->image dependency tests.
129
130 These tests perform clones to/from volumes and images,
131 deleting images/volumes that other volumes were cloned from.
132
133 Images and volumes are expected to be independent at the OpenStack
134 level, but in some configurations (i.e. when using Ceph as storage
135 for both Cinder and Glance) it was possible to end up with images
136 or volumes that could not be deleted. This was fixed for RBD in
137 Cinder 2024.1 change I009d0748f.
138
139 """
140
141 min_microversion = '3.40'
142
143 @classmethod
144 def del_image(cls, image_id):
145 images_client = cls.os_primary.image_client_v2
146 images_client.delete_image(image_id)
147 images_client.wait_for_resource_deletion(image_id)
148
149 @testtools.skipUnless(CONF.volume_feature_enabled.volume_image_dep_tests,
150 reason='Volume/image dependency tests not enabled.')
151 @utils.services('image', 'volume')
152 @decorators.idempotent_id('7a9fba78-2e4b-42b1-9898-bb4a60685320')
153 def test_image_volume_dependencies_1(self):
154 # image -> volume
155 image_args = {
156 'disk_format': 'raw',
157 'container_format': 'bare',
158 'name': 'image-for-test-7a9fba78-2e4b-42b1-9898-bb4a60685320'
159 }
160 image = self.create_image_with_data(**image_args)
161
162 # create a volume from the image
163 vol_args = {'name': ('volume1-for-test'
164 '7a9fba78-2e4b-42b1-9898-bb4a60685320'),
165 'imageRef': image['id']}
166 volume1 = self.create_volume(**vol_args)
167 waiters.wait_for_volume_resource_status(self.volumes_client,
168 volume1['id'],
169 'available')
170
171 self.volumes_client.delete_volume(volume1['id'])
172 self.volumes_client.wait_for_resource_deletion(volume1['id'])
173
174 self.del_image(image['id'])
175
176 @testtools.skipUnless(CONF.volume_feature_enabled.volume_image_dep_tests,
177 reason='Volume/image dependency tests not enabled.')
178 @utils.services('image', 'volume')
179 @decorators.idempotent_id('0e20bd6e-440f-41d8-9b5d-fc047ac00423')
180 def test_image_volume_dependencies_2(self):
181 # image -> volume -> volume
182
183 image_args = {
184 'disk_format': 'raw',
185 'container_format': 'bare',
186 'name': 'image-for-test-0e20bd6e-440f-41d8-9b5d-fc047ac00423'
187 }
188 image = self.create_image_with_data(**image_args)
189
190 # create a volume from the image
191 vol_args = {'name': ('volume1-for-test'
192 '0e20bd6e-440f-41d8-9b5d-fc047ac00423'),
193 'imageRef': image['id']}
194 volume1 = self.create_volume(**vol_args)
195 waiters.wait_for_volume_resource_status(self.volumes_client,
196 volume1['id'],
197 'available')
198
199 vol2_args = {'name': ('volume2-for-test-'
200 '0e20bd6e-440f-41d8-9b5d-fc047ac00423'),
201 'source_volid': volume1['id']}
202 volume2 = self.create_volume(**vol2_args)
203 waiters.wait_for_volume_resource_status(self.volumes_client,
204 volume2['id'],
205 'available')
206
207 self.volumes_client.delete_volume(volume1['id'])
208 self.volumes_client.wait_for_resource_deletion(volume1['id'])
209
210 self.del_image(image['id'])
211
212 @testtools.skipUnless(CONF.volume_feature_enabled.volume_image_dep_tests,
213 reason='Volume/image dependency tests not enabled.')
214 @decorators.idempotent_id('e6050452-06bd-4c7f-9912-45178c83e379')
215 @utils.services('image', 'volume')
216 def test_image_volume_dependencies_3(self):
217 # image -> volume -> snap -> volume
218
219 image_args = {
220 'disk_format': 'raw',
221 'container_format': 'bare',
222 'name': 'image-for-test-e6050452-06bd-4c7f-9912-45178c83e379'
223 }
224 image = self.create_image_with_data(**image_args)
225
226 # create a volume from the image
227 vol_args = {'name': ('volume1-for-test'
228 'e6050452-06bd-4c7f-9912-45178c83e379'),
229 'imageRef': image['id']}
230 volume1 = self.create_volume(**vol_args)
231 waiters.wait_for_volume_resource_status(self.volumes_client,
232 volume1['id'],
233 'available')
234
235 snapshot1 = self.create_snapshot(volume1['id'])
236
237 vol2_args = {'name': ('volume2-for-test-'
238 'e6050452-06bd-4c7f-9912-45178c83e379'),
239 'snapshot_id': snapshot1['id']}
240 volume2 = self.create_volume(**vol2_args)
241 waiters.wait_for_volume_resource_status(self.volumes_client,
242 volume2['id'],
243 'available')
244
245 self.snapshots_client.delete_snapshot(snapshot1['id'])
246 self.snapshots_client.wait_for_resource_deletion(snapshot1['id'])
247
248 self.volumes_client.delete_volume(volume2['id'])
249 self.volumes_client.wait_for_resource_deletion(volume2['id'])
250
251 self.del_image(image['id'])
252
253 self.volumes_client.delete_volume(volume1['id'])
254 self.volumes_client.wait_for_resource_deletion(volume1['id'])
2121 cfg.BoolOpt('volume_revert',
2222 default=False,
2323 help='Enable to run Cinder volume revert tests'),
24 cfg.BoolOpt('volume_image_dep_tests',
25 default=True,
26 help='Run tests for dependencies between images and volumes')
2427 ]
2528
2629 # The barbican service is discovered by config_tempest [1], and will appear
109109 (mount_path, filename))
110110 md5 = ssh_client.exec_command(
111111 'sudo md5sum -b %s/%s|cut -c 1-32' % (mount_path, filename))
112 ssh_client.exec_command('sudo sync')
113112 return md5
114113
115114 def get_md5_from_file(self, instance, instance_ip, filename,
1313 # under the License.
1414
1515 from tempest.common import utils
16 from tempest.common import waiters
17 from tempest import config
1618 from tempest.lib import decorators
1719
20 import testtools
21
1822 from cinder_tempest_plugin.scenario import manager
23
24 CONF = config.CONF
1925
2026
2127 class SnapshotDataIntegrityTests(manager.ScenarioTest):
120126
121127 self.assertEqual(count_snap, i)
122128 self.assertEqual(file_map[i], md5_file)
129
130
131 class SnapshotDependencyTests(manager.ScenarioTest):
132 @testtools.skipUnless(CONF.volume_feature_enabled.volume_image_dep_tests,
133 'dependency tests not enabled')
134 @decorators.idempotent_id('e7028f52-f6d4-479c-8809-6f6cf96cfe0f')
135 @utils.services('image', 'volume')
136 def test_snapshot_removal(self):
137 volume_1 = self.create_volume()
138
139 snapshot_1 = self.create_volume_snapshot(volume_1['id'], force=True)
140 waiters.wait_for_volume_resource_status(
141 self.snapshots_client, snapshot_1['id'], 'available')
142
143 clone_kwargs = {'snapshot_id': snapshot_1['id'],
144 'size': volume_1['size']}
145 volume_2 = self.volumes_client.create_volume(**clone_kwargs)['volume']
146
147 waiters.wait_for_volume_resource_status(
148 self.volumes_client, volume_2['id'], 'available')
149 volume_2 = self.volumes_client.show_volume(volume_2['id'])['volume']
150
151 self.snapshots_client.delete_snapshot(snapshot_1['id'])
152 self.snapshots_client.wait_for_resource_deletion(snapshot_1['id'])
153
154 self.volumes_client.delete_volume(volume_1['id'])
155 self.volumes_client.wait_for_resource_deletion(volume_1['id'])
156
157 self.volumes_client.delete_volume(volume_2['id'])
158 self.volumes_client.wait_for_resource_deletion(volume_2['id'])
1919 Programming Language :: Python :: 3.8
2020 Programming Language :: Python :: 3.9
2121 Programming Language :: Python :: 3.10
22 Programming Language :: Python :: 3.11
2223
2324 [files]
2425 packages =