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
| 4 | 4 | check: |
| 5 | 5 | jobs: |
| 6 | 6 | - 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 | |
| 7 | 10 | - cinder-tempest-plugin-cbak-ceph |
| 11 | - cinder-tempest-plugin-basic-ussuri | |
| 12 | - cinder-tempest-plugin-basic-train | |
| 13 | - cinder-tempest-plugin-basic-stein | |
| 8 | 14 | gate: |
| 9 | 15 | jobs: |
| 10 | 16 | - cinder-tempest-plugin-lvm-lio-barbican |
| 17 | - cinder-tempest-plugin-lvm-tgt-barbican | |
| 11 | 18 | - cinder-tempest-plugin-cbak-ceph |
| 12 | 19 | |
| 13 | 20 | - job: |
| 14 | name: cinder-tempest-plugin-lvm-lio-barbican | |
| 21 | name: cinder-tempest-plugin-lvm-barbican-base | |
| 15 | 22 | 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 | |
| 18 | 24 | parent: devstack-tempest |
| 25 | timeout: 10800 | |
| 19 | 26 | roles: |
| 20 | 27 | - zuul: opendev.org/openstack/cinderlib |
| 21 | 28 | required-projects: |
| 36 | 43 | tempest_test_blacklist: '{{ ansible_user_dir }}/{{ zuul.projects["opendev.org/openstack/tempest"].src_dir }}/tools/tempest-integrated-gate-storage-blacklist.txt' |
| 37 | 44 | tox_envlist: all |
| 38 | 45 | devstack_localrc: |
| 39 | CINDER_ISCSI_HELPER: lioadm | |
| 40 | 46 | CINDER_LVM_TYPE: thin |
| 41 | 47 | CINDER_COORDINATION_URL: 'file://\$state_path' |
| 48 | devstack_local_conf: | |
| 49 | test-config: | |
| 50 | $TEMPEST_CONFIG: | |
| 51 | volume-feature-enabled: | |
| 52 | volume_revert: True | |
| 42 | 53 | devstack_services: |
| 43 | 54 | barbican: true |
| 44 | 55 | tempest_plugins: |
| 57 | 68 | Integration tests that runs with the ceph devstack plugin, py3 |
| 58 | 69 | and enable the backup service. |
| 59 | 70 | 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 | |
| 60 | 77 | devstack_services: |
| 61 | 78 | 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']) |
| 163 | 163 | super(BaseVolumeAdminTest, cls).setup_clients() |
| 164 | 164 | |
| 165 | 165 | 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) |
| 8 | 8 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 9 | 9 | # License for the specific language governing permissions and limitations |
| 10 | 10 | # under the License. |
| 11 | ||
| 12 | import io | |
| 11 | 13 | |
| 12 | 14 | from tempest.common import waiters |
| 13 | 15 | from tempest import config |
| 76 | 78 | waiters.wait_for_volume_resource_status(self.volumes_client, |
| 77 | 79 | v['id'], |
| 78 | 80 | '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") |
| 17 | 17 | |
| 18 | 18 | from oslo_serialization import jsonutils as json |
| 19 | 19 | from six.moves import http_client |
| 20 | from tempest import exceptions | |
| 21 | 20 | from tempest.lib.common import rest_client |
| 22 | 21 | from tempest.lib import exceptions as lib_exc |
| 22 | ||
| 23 | from cinder_tempest_plugin import exceptions as volume_exc | |
| 23 | 24 | |
| 24 | 25 | |
| 25 | 26 | class ConsistencyGroupsClient(rest_client.RestClient): |
| 136 | 137 | body = self.show_consistencygroup(cg_id)['consistencygroup'] |
| 137 | 138 | cg_status = body['status'] |
| 138 | 139 | if cg_status == 'error': |
| 139 | raise exceptions.ConsistencyGroupException(cg_id=cg_id) | |
| 140 | raise volume_exc.ConsistencyGroupException(cg_id=cg_id) | |
| 140 | 141 | |
| 141 | 142 | if int(time.time()) - start >= self.build_timeout: |
| 142 | 143 | message = ('Consistency group %s failed to reach %s status ' |
| 143 | 144 | '(current %s) within the required time (%s s).' % |
| 144 | 145 | (cg_id, status, cg_status, |
| 145 | 146 | self.build_timeout)) |
| 146 | raise exceptions.TimeoutException(message) | |
| 147 | raise lib_exc.TimeoutException(message) | |
| 147 | 148 | |
| 148 | 149 | def wait_for_consistencygroup_deletion(self, cg_id): |
| 149 | 150 | """Waits for consistency group deletion""" |
| 154 | 155 | except lib_exc.NotFound: |
| 155 | 156 | return |
| 156 | 157 | if int(time.time()) - start_time >= self.build_timeout: |
| 157 | raise exceptions.TimeoutException | |
| 158 | raise lib_exc.TimeoutException | |
| 158 | 159 | time.sleep(self.build_interval) |
| 159 | 160 | |
| 160 | 161 | def wait_for_cgsnapshot_status(self, cgsnapshot_id, status): |
| 168 | 169 | body = self.show_cgsnapshot(cgsnapshot_id)['cgsnapshot'] |
| 169 | 170 | cgsnapshot_status = body['status'] |
| 170 | 171 | if cgsnapshot_status == 'error': |
| 171 | raise exceptions.ConsistencyGroupSnapshotException( | |
| 172 | raise volume_exc.ConsistencyGroupSnapshotException( | |
| 172 | 173 | cgsnapshot_id=cgsnapshot_id) |
| 173 | 174 | |
| 174 | 175 | if int(time.time()) - start >= self.build_timeout: |
| 177 | 178 | '(%s s).' % |
| 178 | 179 | (cgsnapshot_id, status, cgsnapshot_status, |
| 179 | 180 | self.build_timeout)) |
| 180 | raise exceptions.TimeoutException(message) | |
| 181 | raise lib_exc.TimeoutException(message) | |
| 181 | 182 | |
| 182 | 183 | def wait_for_cgsnapshot_deletion(self, cgsnapshot_id): |
| 183 | 184 | """Waits for consistency group snapshot deletion""" |
| 188 | 189 | except lib_exc.NotFound: |
| 189 | 190 | return |
| 190 | 191 | if int(time.time()) - start_time >= self.build_timeout: |
| 191 | raise exceptions.TimeoutException | |
| 192 | raise lib_exc.TimeoutException | |
| 192 | 193 | time.sleep(self.build_interval) |
| 0 | - hosts: all | |
| 0 | - hosts: tempest | |
| 1 | 1 | vars: |
| 2 | 2 | tox_envlist: functional |
| 3 | 3 | zuul_work_dir: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/cinderlib'].src_dir }}" |
| 18 | 18 | - setup-tempest-data-dir |
| 19 | 19 | - acl-devstack-files |
| 20 | 20 | - 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 | |
| 22 | 22 | ignore_errors: yes |
| 23 | 23 | - role: change-devstack-data-owner |
| 24 | 24 | devstack_data_subdir_changed: cinder |
| 25 | 25 | devstack_data_subdir_owner: zuul |
| 26 | 26 | - role: run-cinderlib-tests |
| 27 | tox_install_siblings: false | |
| 27 | 28 | 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 |
| 20 | 20 | packages = |
| 21 | 21 | cinder_tempest_plugin |
| 22 | 22 | |
| 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 | ||
| 46 | 23 | [entry_points] |
| 47 | 24 | tempest.test_plugins = |
| 48 | 25 | cinder_tests = cinder_tempest_plugin.plugin:CinderTempestPlugin |
| 12 | 12 | # See the License for the specific language governing permissions and |
| 13 | 13 | # limitations under the License. |
| 14 | 14 | |
| 15 | # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT | |
| 16 | 15 | 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 | |
| 25 | 16 | |
| 26 | 17 | setuptools.setup( |
| 27 | 18 | setup_requires=['pbr>=2.0.0'], |
| 1 | 1 | # of appearance. Changing the order has an impact on the overall integration |
| 2 | 2 | # process, which may cause wedges in the gate later. |
| 3 | 3 | |
| 4 | hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 | |
| 4 | hacking>=3.0.1,<3.1 # Apache-2.0 | |
| 5 | 5 | |
| 6 | 6 | coverage!=4.4,>=4.0 # Apache-2.0 |
| 7 | 7 | python-subunit>=1.0.0 # Apache-2.0/BSD |
| 8 | 8 | [testenv] |
| 9 | 9 | basepython = python3 |
| 10 | 10 | usedevelop = True |
| 11 | install_command = pip install {opts} {packages} | |
| 12 | 11 | setenv = |
| 13 | 12 | VIRTUAL_ENV={envdir} |
| 14 | 13 | 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} | |
| 16 | 15 | -r{toxinidir}/test-requirements.txt |
| 17 | 16 | commands = python setup.py test --slowest --testr-args='{posargs}' |
| 18 | 17 | |
| 24 | 23 | |
| 25 | 24 | [flake8] |
| 26 | 25 | # E123, E125 skipped as they are invalid PEP-8. |
| 27 | ||
| 26 | # W503 line break before binary operator | |
| 27 | # W504 line break after binary operator | |
| 28 | 28 | show-source = True |
| 29 | ignore = E123,E125 | |
| 29 | ignore = E123,E125,W503,W504 | |
| 30 | 30 | builtins = _ |
| 31 | 31 | exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build |