Codebase list cinder-tempest-plugin / b544436
Merge tag '1.1.0' into debian/victoria cinder-tempest-plugin 1.1.0 release meta:version: 1.1.0 meta:diff-start: - meta:series: victoria meta:release-type: release meta:pypi: no meta:first: yes meta:release:Author: Brian Rosmaita <rosmaita.fossdev@gmail.com> meta:release:Commit: Brian Rosmaita <rosmaita.fossdev@gmail.com> meta:release:Change-Id: If7aa154745235ab13a55585a096f29a62ca5c35c meta:release:Code-Review+2: Sean McGinnis <sean.mcginnis@gmail.com> meta:release:Code-Review+2: Hervé Beraud <hberaud@redhat.com> meta:release:Workflow+1: Hervé Beraud <hberaud@redhat.com> Thomas Goirand 5 years ago
12 changed file(s) with 401 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
44 check:
55 jobs:
66 - cinder-tempest-plugin-lvm-lio-barbican
7 - cinder-tempest-plugin-lvm-lio-barbican-centos-8:
8 voting: false
9 - cinder-tempest-plugin-lvm-tgt-barbican
710 - cinder-tempest-plugin-cbak-ceph
11 - cinder-tempest-plugin-basic-ussuri
12 - cinder-tempest-plugin-basic-train
13 - cinder-tempest-plugin-basic-stein
814 gate:
915 jobs:
1016 - cinder-tempest-plugin-lvm-lio-barbican
17 - cinder-tempest-plugin-lvm-tgt-barbican
1118 - cinder-tempest-plugin-cbak-ceph
1219
1320 - job:
14 name: cinder-tempest-plugin-lvm-lio-barbican
21 name: cinder-tempest-plugin-lvm-barbican-base
1522 description: |
16 This jobs configures Cinder with LVM, LIO, barbican and
17 runs tempest tests and cinderlib tests.
23 This is a base job for lvm with lio & tgt targets
1824 parent: devstack-tempest
25 timeout: 10800
1926 roles:
2027 - zuul: opendev.org/openstack/cinderlib
2128 required-projects:
3643 tempest_test_blacklist: '{{ ansible_user_dir }}/{{ zuul.projects["opendev.org/openstack/tempest"].src_dir }}/tools/tempest-integrated-gate-storage-blacklist.txt'
3744 tox_envlist: all
3845 devstack_localrc:
39 CINDER_ISCSI_HELPER: lioadm
4046 CINDER_LVM_TYPE: thin
4147 CINDER_COORDINATION_URL: 'file://\$state_path'
48 devstack_local_conf:
49 test-config:
50 $TEMPEST_CONFIG:
51 volume-feature-enabled:
52 volume_revert: True
4253 devstack_services:
4354 barbican: true
4455 tempest_plugins:
5768 Integration tests that runs with the ceph devstack plugin, py3
5869 and enable the backup service.
5970 vars:
71 tempest_black_regex: '(VolumesBackupsTest.test_bootable_volume_backup_and_restore|TestVolumeBackupRestore.test_volume_backup_restore)'
72 devstack_local_conf:
73 test-config:
74 $TEMPEST_CONFIG:
75 volume-feature-enabled:
76 volume_revert: True
6077 devstack_services:
6178 c-bak: true
79
80 # variant for pre-Ussuri branches (no volume revert for Ceph),
81 # should this job be used on those branches
82 - job:
83 name: cinder-tempest-plugin-cbak-ceph
84 branches: ^(?=stable/(ocata|pike|queens|rocky|stein|train)).*$
85 vars:
86 tempest_black_regex: ''
87 devstack_local_conf:
88 test-config:
89 $TEMPEST_CONFIG:
90 volume-feature-enabled:
91 volume_revert: False
92
93 - job:
94 name: cinder-tempest-plugin-lvm-lio-barbican
95 description: |
96 This jobs configures Cinder with LVM, LIO, barbican and
97 runs tempest tests and cinderlib tests.
98 parent: cinder-tempest-plugin-lvm-barbican-base
99 vars:
100 devstack_localrc:
101 CINDER_ISCSI_HELPER: lioadm
102
103 - job:
104 name: cinder-tempest-plugin-lvm-lio-barbican-centos-8
105 parent: cinder-tempest-plugin-lvm-lio-barbican
106 nodeset: devstack-single-node-centos-8
107 description: |
108 This jobs configures Cinder with LVM, LIO, barbican and
109 runs tempest tests and cinderlib tests on CentOS 8.
110
111 - job:
112 name: cinder-tempest-plugin-lvm-tgt-barbican
113 description: |
114 This jobs configures Cinder with LVM, tgt, barbican and
115 runs tempest tests and cinderlib tests.
116 parent: cinder-tempest-plugin-lvm-barbican-base
117
118 - job:
119 name: cinder-tempest-plugin-basic
120 parent: devstack-tempest
121 description: |
122 Cinder tempest plugin tests job which run only cinder-tempest-plugin
123 tests.
124 required-projects:
125 - opendev.org/openstack/cinder-tempest-plugin
126 vars:
127 devstack_localrc:
128 TEMPEST_VOLUME_REVERT_TO_SNAPSHOT: True
129 tox_envlist: all
130 tempest_test_regex: cinder_tempest_plugin
131 tempest_plugins:
132 - cinder-tempest-plugin
133 irrelevant-files:
134 - ^.*\.rst$
135 - ^doc/.*$
136 - ^releasenotes/.*$
137
138 - job:
139 name: cinder-tempest-plugin-basic-ussuri
140 parent: cinder-tempest-plugin-basic
141 override-checkout: stable/ussuri
142
143 - job:
144 name: cinder-tempest-plugin-basic-train
145 parent: cinder-tempest-plugin-basic
146 override-checkout: stable/train
147 vars:
148 devstack_localrc:
149 USE_PYTHON3: True
150
151 - job:
152 name: cinder-tempest-plugin-basic-stein
153 parent: cinder-tempest-plugin-basic
154 override-checkout: stable/stein
155 vars:
156 devstack_localrc:
157 USE_PYTHON3: True
0 # Copyright (C) 2020 Canonical Ltd.
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 from tempest.common import waiters
16 from tempest import config
17 from tempest.lib import decorators
18 from tempest.lib import exceptions
19
20 from cinder_tempest_plugin.api.volume import base
21
22 CONF = config.CONF
23
24
25 class VolumesBackupsTest(base.BaseVolumeAdminTest):
26 @classmethod
27 def setup_clients(cls):
28 super(VolumesBackupsTest, cls).setup_clients()
29 cls.admin_volume_client = cls.os_admin.volumes_client_latest
30 cls.backups_client = cls.os_primary.backups_client_latest
31 cls.volumes_client = cls.os_primary.volumes_client_latest
32
33 @classmethod
34 def skip_checks(cls):
35 super(VolumesBackupsTest, cls).skip_checks()
36 if not CONF.volume_feature_enabled.backup:
37 raise cls.skipException("Cinder backup feature disabled")
38
39 @decorators.idempotent_id('2daadb2e-409a-4ede-a6ce-6002ec324372')
40 def test_backup_crossproject_admin_negative(self):
41
42 # create vol as user
43 volume = self.volumes_client.create_volume(
44 size=CONF.volume.volume_size)['volume']
45 waiters.wait_for_volume_resource_status(
46 self.volumes_client,
47 volume['id'], 'available')
48
49 # create backup as user
50 backup = self.backups_client.create_backup(
51 volume_id=volume['id'])['backup']
52 waiters.wait_for_volume_resource_status(
53 self.backups_client,
54 backup['id'], 'available')
55
56 # try to create incremental backup as admin
57 self.assertRaises(
58 exceptions.BadRequest, self.admin_backups_client.create_backup,
59 volume_id=volume['id'], incremental=True)
60
61 @decorators.idempotent_id('b9feb593-5809-4207-90d3-28e627730f13')
62 def test_backup_crossproject_user_negative(self):
63
64 # create vol as user
65 volume = self.volumes_client.create_volume(
66 size=CONF.volume.volume_size)['volume']
67 waiters.wait_for_volume_resource_status(
68 self.volumes_client,
69 volume['id'], 'available')
70
71 # create backup as admin
72 backup = self.admin_backups_client.create_backup(
73 volume_id=volume['id'])['backup']
74 waiters.wait_for_volume_resource_status(
75 self.admin_backups_client,
76 backup['id'], 'available')
77
78 # try to create incremental backup as user
79 self.assertRaises(
80 exceptions.BadRequest, self.backups_client.create_backup,
81 volume_id=volume['id'], incremental=True)
82
83 @decorators.idempotent_id('ce15f528-bfc1-492d-81db-b6168b631587')
84 def test_incremental_backup_respective_parents(self):
85
86 # create vol as user
87 volume = self.volumes_client.create_volume(
88 size=CONF.volume.volume_size)['volume']
89 waiters.wait_for_volume_resource_status(
90 self.volumes_client,
91 volume['id'], 'available')
92
93 # create backup as admin
94 backup_adm = self.admin_backups_client.create_backup(
95 volume_id=volume['id'])['backup']
96 waiters.wait_for_volume_resource_status(
97 self.admin_backups_client,
98 backup_adm['id'], 'available')
99
100 # create backup as user
101 backup_usr = self.backups_client.create_backup(
102 volume_id=volume['id'])['backup']
103 waiters.wait_for_volume_resource_status(
104 self.backups_client,
105 backup_usr['id'], 'available')
106
107 # refresh admin backup and assert no child backups
108 backup_adm = self.admin_backups_client.show_backup(
109 backup_adm['id'])['backup']
110 self.assertFalse(backup_adm['has_dependent_backups'])
111
112 # create incremental backup as admin
113 backup_adm_inc = self.admin_backups_client.create_backup(
114 volume_id=volume['id'], incremental=True)['backup']
115 waiters.wait_for_volume_resource_status(
116 self.admin_backups_client,
117 backup_adm_inc['id'], 'available')
118
119 # refresh user backup and assert no child backups
120 backup_usr = self.backups_client.show_backup(
121 backup_usr['id'])['backup']
122 self.assertFalse(backup_usr['has_dependent_backups'])
123
124 # refresh admin backup and assert it has childs
125 backup_adm = self.admin_backups_client.show_backup(
126 backup_adm['id'])['backup']
127 self.assertTrue(backup_adm['has_dependent_backups'])
128
129 # create incremental backup as user
130 backup_usr_inc = self.backups_client.create_backup(
131 volume_id=volume['id'], incremental=True)['backup']
132 waiters.wait_for_volume_resource_status(
133 self.backups_client,
134 backup_usr_inc['id'], 'available')
135
136 # refresh user backup and assert it has childs
137 backup_usr = self.backups_client.show_backup(
138 backup_usr['id'])['backup']
139 self.assertTrue(backup_usr['has_dependent_backups'])
163163 super(BaseVolumeAdminTest, cls).setup_clients()
164164
165165 cls.admin_volume_types_client = cls.os_admin.volume_types_client_latest
166 cls.admin_backups_client = cls.os_admin.backups_client_latest
167 cls.admin_volumes_client = cls.os_admin.volumes_client_latest
168
169 @classmethod
170 def create_volume_type(cls, name=None, **kwargs):
171 """Create a test volume-type"""
172
173 name = name or data_utils.rand_name(cls.__name__ + '-volume-type')
174 volume_type = cls.admin_volume_types_client.create_volume_type(
175 name=name, **kwargs)['volume_type']
176 cls.addClassResourceCleanup(cls._clear_volume_type, volume_type)
177 return volume_type
178
179 @classmethod
180 def _clear_volume_type(cls, volume_type):
181 # If image caching is enabled, we must delete the cached volume
182 # before cinder will allow us to delete the volume_type. This function
183 # solves that problem by taking the brute-force approach of deleting
184 # any volumes of this volume_type that exist *no matter what project
185 # they are in*. Since this won't happen until the teardown of the
186 # test class, that should be OK.
187 type_id = volume_type['id']
188 type_name = volume_type['name']
189
190 volumes = cls.admin_volumes_client.list_volumes(
191 detail=True, params={'all_tenants': 1})['volumes']
192 for volume in [v for v in volumes if v['volume_type'] == type_name]:
193 test_utils.call_and_ignore_notfound_exc(
194 cls.admin_volumes_client.delete_volume, volume['id'])
195 cls.admin_volumes_client.wait_for_resource_deletion(volume['id'])
196
197 test_utils.call_and_ignore_notfound_exc(
198 cls.admin_volume_types_client.delete_volume_type, type_id)
199 test_utils.call_and_ignore_notfound_exc(
200 cls.admin_volume_types_client.wait_for_resource_deletion, type_id)
88 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
99 # License for the specific language governing permissions and limitations
1010 # under the License.
11
12 import io
1113
1214 from tempest.common import waiters
1315 from tempest import config
7678 waiters.wait_for_volume_resource_status(self.volumes_client,
7779 v['id'],
7880 'available')
81
82
83 class VolumeAndVolumeTypeFromImageTest(base.BaseVolumeAdminTest):
84 # needs AdminTest as superclass to manipulate volume_types
85
86 @classmethod
87 def skip_checks(cls):
88 super(VolumeAndVolumeTypeFromImageTest, cls).skip_checks()
89 if not CONF.service_available.glance:
90 raise cls.skipException("Glance service is disabled")
91
92 @classmethod
93 def create_image_with_data(cls, **kwargs):
94 # we do this as a class method so we can use the
95 # addClassResourceCleanup functionality of tempest.test.BaseTestCase
96 images_client = cls.os_primary.image_client_v2
97 if 'min_disk' not in kwargs:
98 kwargs['min_disk'] = 1
99 response = images_client.create_image(**kwargs)
100 image_id = response['id']
101 cls.addClassResourceCleanup(
102 images_client.wait_for_resource_deletion, image_id)
103 cls.addClassResourceCleanup(
104 test_utils.call_and_ignore_notfound_exc,
105 images_client.delete_image, image_id)
106
107 # upload "data" to image
108 image_file = io.BytesIO(data_utils.random_bytes(size=1024))
109 images_client.store_image_file(image_id, image_file)
110
111 waiters.wait_for_image_status(images_client, image_id, 'active')
112 image = images_client.show_image(image_id)
113 return image
114
115 @decorators.idempotent_id('6e9266ff-a917-4dd5-aa4a-c36e59e7a2a6')
116 def test_create_from_image_with_volume_type_image_property(self):
117 """Verify that the cinder_img_volume_type image property works.
118
119 When a volume is created from an image containing the
120 cinder_img_volume_type property and no volume_type is specified
121 in the volume-create request, the volume_type of the resulting
122 volume should be the one specified by the image property.
123 """
124
125 volume_type_meta = 'cinder_img_volume_type'
126 volume_type_name = 'vol-type-for-6e9266ff-a917-4dd5-aa4a-c36e59e7a2a6'
127 description = ('Generic volume_type for test '
128 '6e9266ff-a917-4dd5-aa4a-c36e59e7a2a6')
129 proto = CONF.volume.storage_protocol
130 vendor = CONF.volume.vendor_name
131 extra_specs = {"storage_protocol": proto,
132 "vendor_name": vendor}
133 kwargs = {'description': description,
134 'extra_specs': extra_specs,
135 'os-volume-type-access:is_public': True}
136 volume_type = self.create_volume_type(name=volume_type_name,
137 **kwargs)
138 # quick sanity check
139 self.assertEqual(volume_type_name, volume_type['name'])
140
141 # create an image in glance
142 kwargs = {'disk_format': 'raw',
143 'container_format': 'bare',
144 'name': ('image-for-test-'
145 '6e9266ff-a917-4dd5-aa4a-c36e59e7a2a6'),
146 'visibility': 'private',
147 volume_type_meta: volume_type_name}
148 image = self.create_image_with_data(**kwargs)
149 # quick sanity check
150 self.assertEqual(volume_type_name, image[volume_type_meta])
151
152 # create volume from image
153 kwargs = {'name': ('volume-for-test-'
154 '6e9266ff-a917-4dd5-aa4a-c36e59e7a2a6'),
155 'imageRef': image['id']}
156 # this is the whole point of the test, so make sure this is true
157 self.assertNotIn('volume_type', kwargs)
158 volume = self.create_volume(**kwargs)
159
160 found_volume_type = volume['volume_type']
161 self.assertEqual(volume_type_name, found_volume_type)
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 import exceptions
13
14
15 class ConsistencyGroupException(exceptions.TempestException):
16 message = "Consistency group %(cg_id)s failed and is in ERROR status"
17
18
19 class ConsistencyGroupSnapshotException(exceptions.TempestException):
20 message = ("Consistency group snapshot %(cgsnapshot_id)s failed and is "
21 "in ERROR status")
1717
1818 from oslo_serialization import jsonutils as json
1919 from six.moves import http_client
20 from tempest import exceptions
2120 from tempest.lib.common import rest_client
2221 from tempest.lib import exceptions as lib_exc
22
23 from cinder_tempest_plugin import exceptions as volume_exc
2324
2425
2526 class ConsistencyGroupsClient(rest_client.RestClient):
136137 body = self.show_consistencygroup(cg_id)['consistencygroup']
137138 cg_status = body['status']
138139 if cg_status == 'error':
139 raise exceptions.ConsistencyGroupException(cg_id=cg_id)
140 raise volume_exc.ConsistencyGroupException(cg_id=cg_id)
140141
141142 if int(time.time()) - start >= self.build_timeout:
142143 message = ('Consistency group %s failed to reach %s status '
143144 '(current %s) within the required time (%s s).' %
144145 (cg_id, status, cg_status,
145146 self.build_timeout))
146 raise exceptions.TimeoutException(message)
147 raise lib_exc.TimeoutException(message)
147148
148149 def wait_for_consistencygroup_deletion(self, cg_id):
149150 """Waits for consistency group deletion"""
154155 except lib_exc.NotFound:
155156 return
156157 if int(time.time()) - start_time >= self.build_timeout:
157 raise exceptions.TimeoutException
158 raise lib_exc.TimeoutException
158159 time.sleep(self.build_interval)
159160
160161 def wait_for_cgsnapshot_status(self, cgsnapshot_id, status):
168169 body = self.show_cgsnapshot(cgsnapshot_id)['cgsnapshot']
169170 cgsnapshot_status = body['status']
170171 if cgsnapshot_status == 'error':
171 raise exceptions.ConsistencyGroupSnapshotException(
172 raise volume_exc.ConsistencyGroupSnapshotException(
172173 cgsnapshot_id=cgsnapshot_id)
173174
174175 if int(time.time()) - start >= self.build_timeout:
177178 '(%s s).' %
178179 (cgsnapshot_id, status, cgsnapshot_status,
179180 self.build_timeout))
180 raise exceptions.TimeoutException(message)
181 raise lib_exc.TimeoutException(message)
181182
182183 def wait_for_cgsnapshot_deletion(self, cgsnapshot_id):
183184 """Waits for consistency group snapshot deletion"""
188189 except lib_exc.NotFound:
189190 return
190191 if int(time.time()) - start_time >= self.build_timeout:
191 raise exceptions.TimeoutException
192 raise lib_exc.TimeoutException
192193 time.sleep(self.build_interval)
0 - hosts: all
0 - hosts: tempest
11 vars:
22 tox_envlist: functional
33 zuul_work_dir: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/cinderlib'].src_dir }}"
1818 - setup-tempest-data-dir
1919 - acl-devstack-files
2020 - role: run-tempest
21 # ignore the errors, so that run-cinderlib-tests is always executed
21 # ignore the errors for now, so that run-cinderlib-tests is always executed
2222 ignore_errors: yes
2323 - role: change-devstack-data-owner
2424 devstack_data_subdir_changed: cinder
2525 devstack_data_subdir_owner: zuul
2626 - role: run-cinderlib-tests
27 tox_install_siblings: false
2728 cinderlib_base_dir: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/cinderlib'].src_dir }}"
29 post_tasks:
30 - name: Fail if the first tempest run did not work
31 fail:
32 msg: "tempest run returned with an error"
33 when: tempest_run_result is defined and tempest_run_result.rc != 0
2020 packages =
2121 cinder_tempest_plugin
2222
23 [build_sphinx]
24 all-files = 1
25 warning-is-error = 1
26 source-dir = doc/source
27 build-dir = doc/build
28
29 [upload_sphinx]
30 upload-dir = doc/build/html
31
32 [compile_catalog]
33 directory = cinder_tempest_plugin/locale
34 domain = cinder_tempest_plugin
35
36 [update_catalog]
37 domain = cinder_tempest_plugin
38 output_dir = cinder_tempest_plugin/locale
39 input_file = cinder_tempest_plugin/locale/cinder_tempest_plugin.pot
40
41 [extract_messages]
42 keywords = _ gettext ngettext l_ lazy_gettext
43 mapping_file = babel.cfg
44 output_file = cinder_tempest_plugin/locale/cinder_tempest_plugin.pot
45
4623 [entry_points]
4724 tempest.test_plugins =
4825 cinder_tests = cinder_tempest_plugin.plugin:CinderTempestPlugin
1212 # See the License for the specific language governing permissions and
1313 # limitations under the License.
1414
15 # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
1615 import setuptools
17
18 # In python < 2.7.4, a lazy loading of package `pbr` will break
19 # setuptools if some other modules registered functions in `atexit`.
20 # solution from: http://bugs.python.org/issue15881#msg170215
21 try:
22 import multiprocessing # noqa
23 except ImportError:
24 pass
2516
2617 setuptools.setup(
2718 setup_requires=['pbr>=2.0.0'],
11 # of appearance. Changing the order has an impact on the overall integration
22 # process, which may cause wedges in the gate later.
33
4 hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
4 hacking>=3.0.1,<3.1 # Apache-2.0
55
66 coverage!=4.4,>=4.0 # Apache-2.0
77 python-subunit>=1.0.0 # Apache-2.0/BSD
88 [testenv]
99 basepython = python3
1010 usedevelop = True
11 install_command = pip install {opts} {packages}
1211 setenv =
1312 VIRTUAL_ENV={envdir}
1413 PYTHONWARNINGS=default::DeprecationWarning
15 deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
14 deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
1615 -r{toxinidir}/test-requirements.txt
1716 commands = python setup.py test --slowest --testr-args='{posargs}'
1817
2423
2524 [flake8]
2625 # E123, E125 skipped as they are invalid PEP-8.
27
26 # W503 line break before binary operator
27 # W504 line break after binary operator
2828 show-source = True
29 ignore = E123,E125
29 ignore = E123,E125,W503,W504
3030 builtins = _
3131 exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build