Codebase list cinder-tempest-plugin / 75511e3
Refactored cinder tempest tests to cinder_tempest_plugin * As per the current codebase of cinder tempest plugin, it is getting dumped in the cinder/tests and the package name is setup.cfg is cinder_tempest_plugin which does not exists. So i refactored to give a proper tempest plugin shape. Change-Id: Ia78ea53a99923844f40fb4e9fe22ec0da4b0c335 Chandan Kumar 8 years ago
31 changed file(s) with 1066 addition(s) and 1066 deletion(s). Raw diff Collapse all Expand all
+0
-0
cinder/tests/tempest/__init__.py less more
(Empty file)
+0
-0
cinder/tests/tempest/api/__init__.py less more
(Empty file)
+0
-0
cinder/tests/tempest/api/volume/__init__.py less more
(Empty file)
+0
-170
cinder/tests/tempest/api/volume/base.py less more
0 # Copyright 2017 NEC Corporation.
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.api.volume import api_microversion_fixture
16 from tempest.common import compute
17 from tempest.common import waiters
18 from tempest import config
19 from tempest.lib.common import api_version_utils
20 from tempest.lib.common.utils import data_utils
21 from tempest.lib.common.utils import test_utils
22 from tempest.lib import exceptions
23 from tempest import test
24
25 CONF = config.CONF
26
27
28 class BaseVolumeTest(api_version_utils.BaseMicroversionTest,
29 test.BaseTestCase):
30 """Base test case class for all Cinder API tests."""
31
32 _api_version = 2
33 credentials = ['primary']
34
35 @classmethod
36 def skip_checks(cls):
37 super(BaseVolumeTest, cls).skip_checks()
38
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 if cls._api_version == 2:
43 if not CONF.volume_feature_enabled.api_v2:
44 msg = "Volume API v2 is disabled"
45 raise cls.skipException(msg)
46 elif cls._api_version == 3:
47 if not CONF.volume_feature_enabled.api_v3:
48 msg = "Volume API v3 is disabled"
49 raise cls.skipException(msg)
50 else:
51 msg = ("Invalid Cinder API version (%s)" % cls._api_version)
52 raise exceptions.InvalidConfiguration(msg)
53
54 api_version_utils.check_skip_with_microversion(
55 cls.min_microversion, cls.max_microversion,
56 CONF.volume.min_microversion, CONF.volume.max_microversion)
57
58 @classmethod
59 def setup_clients(cls):
60 super(BaseVolumeTest, cls).setup_clients()
61 if cls._api_version == 3:
62 cls.backups_client = cls.os_primary.backups_v3_client
63 cls.volumes_client = cls.os_primary.volumes_v3_client
64 else:
65 cls.backups_client = cls.os_primary.backups_v2_client
66 cls.volumes_client = cls.os_primary.volumes_v2_client
67
68 cls.snapshots_client = cls.os_primary.snapshots_v2_client
69
70 @classmethod
71 def setup_credentials(cls):
72 cls.set_network_resources()
73 super(BaseVolumeTest, cls).setup_credentials()
74
75 def setUp(self):
76 super(BaseVolumeTest, self).setUp()
77 self.useFixture(api_microversion_fixture.APIMicroversionFixture(
78 self.request_microversion))
79
80 @classmethod
81 def resource_setup(cls):
82 super(BaseVolumeTest, cls).resource_setup()
83 cls.request_microversion = (
84 api_version_utils.select_request_microversion(
85 cls.min_microversion,
86 CONF.volume.min_microversion))
87
88 @classmethod
89 def create_volume(cls, wait_until='available', **kwargs):
90 """Wrapper utility that returns a test volume.
91
92 :param wait_until: wait till volume status.
93 """
94 if 'size' not in kwargs:
95 kwargs['size'] = CONF.volume.volume_size
96
97 if 'imageRef' in kwargs:
98 image = cls.os_primary.image_client_v2.show_image(
99 kwargs['imageRef'])
100 min_disk = image['min_disk']
101 kwargs['size'] = max(kwargs['size'], min_disk)
102
103 if 'name' not in kwargs:
104 name = data_utils.rand_name(cls.__name__ + '-Volume')
105 kwargs['name'] = name
106
107 volume = cls.volumes_client.create_volume(**kwargs)['volume']
108 cls.addClassResourceCleanup(
109 cls.volumes_client.wait_for_resource_deletion, volume['id'])
110 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
111 cls.volumes_client.delete_volume,
112 volume['id'])
113 waiters.wait_for_volume_resource_status(cls.volumes_client,
114 volume['id'], wait_until)
115 return volume
116
117 @classmethod
118 def create_snapshot(cls, volume_id=1, **kwargs):
119 """Wrapper utility that returns a test snapshot."""
120 if 'name' not in kwargs:
121 name = data_utils.rand_name(cls.__name__ + '-Snapshot')
122 kwargs['name'] = name
123
124 snapshot = cls.snapshots_client.create_snapshot(
125 volume_id=volume_id, **kwargs)['snapshot']
126 cls.addClassResourceCleanup(
127 cls.snapshots_client.wait_for_resource_deletion, snapshot['id'])
128 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
129 cls.snapshots_client.delete_snapshot,
130 snapshot['id'])
131 waiters.wait_for_volume_resource_status(cls.snapshots_client,
132 snapshot['id'], 'available')
133 return snapshot
134
135 def create_backup(self, volume_id, backup_client=None, **kwargs):
136 """Wrapper utility that returns a test backup."""
137 if backup_client is None:
138 backup_client = self.backups_client
139 if 'name' not in kwargs:
140 name = data_utils.rand_name(self.__class__.__name__ + '-Backup')
141 kwargs['name'] = name
142
143 backup = backup_client.create_backup(
144 volume_id=volume_id, **kwargs)['backup']
145 self.addCleanup(backup_client.delete_backup, backup['id'])
146 waiters.wait_for_volume_resource_status(backup_client, backup['id'],
147 'available')
148 return backup
149
150 def create_server(self, wait_until='ACTIVE', **kwargs):
151 name = kwargs.pop(
152 'name',
153 data_utils.rand_name(self.__class__.__name__ + '-instance'))
154
155 tenant_network = self.get_tenant_network()
156 body, _ = compute.create_test_server(
157 self.os_primary,
158 tenant_network=tenant_network,
159 name=name,
160 wait_until=wait_until,
161 **kwargs)
162
163 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
164 waiters.wait_for_server_termination,
165 self.os_primary.servers_client, body['id'])
166 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
167 self.os_primary.servers_client.delete_server,
168 body['id'])
169 return body
+0
-283
cinder/tests/tempest/api/volume/test_consistencygroups.py less more
0 # Copyright (C) 2015 EMC Corporation.
1 # Copyright (C) 2016 Pure Storage, Inc.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 from tempest.common import waiters
17 from tempest import config
18 from tempest.lib.common.utils import data_utils
19 from tempest.lib import decorators
20
21 from cinder.tests.tempest.api.volume import base
22 from cinder.tests.tempest import cinder_clients
23
24 CONF = config.CONF
25
26
27 class ConsistencyGroupsV2Test(base.BaseVolumeTest):
28 @classmethod
29 def setup_clients(cls):
30 cls._api_version = 2
31 super(ConsistencyGroupsV2Test, cls).setup_clients()
32 cls.admin_volume_client = cls.os_admin.volumes_v2_client
33
34 manager = cinder_clients.Manager(cls.os_admin)
35 cls.consistencygroups_adm_client = manager.consistencygroups_adm_client
36
37 @classmethod
38 def skip_checks(cls):
39 super(ConsistencyGroupsV2Test, cls).skip_checks()
40 if not CONF.volume_feature_enabled.consistency_group:
41 raise cls.skipException("Cinder consistency group "
42 "feature disabled")
43
44 def _delete_consistencygroup(self, cg_id):
45 self.consistencygroups_adm_client.delete_consistencygroup(cg_id)
46 vols = self.admin_volume_client.list_volumes(detail=True)['volumes']
47 for vol in vols:
48 if vol['consistencygroup_id'] == cg_id:
49 self.admin_volume_client.wait_for_resource_deletion(vol['id'])
50 self.consistencygroups_adm_client.wait_for_consistencygroup_deletion(
51 cg_id)
52
53 def _delete_cgsnapshot(self, cgsnapshot_id, cg_id):
54 self.consistencygroups_adm_client.delete_cgsnapshot(cgsnapshot_id)
55 vols = self.admin_volume_client.list_volumes(detail=True)['volumes']
56 snapshots = self.os_admin.snapshots_v2_client.list_snapshots(
57 detail=True)['snapshots']
58 for vol in vols:
59 for snap in snapshots:
60 if (vol['consistencygroup_id'] == cg_id and
61 vol['id'] == snap['volume_id']):
62 (self.snapshots_client.
63 wait_for_resource_deletion(snap['id']))
64 self.consistencygroups_adm_client.wait_for_cgsnapshot_deletion(
65 cgsnapshot_id)
66
67 @decorators.idempotent_id('3fe776ba-ec1f-4e6c-8d78-4b14c3a7fc44')
68 def test_consistencygroup_create_delete(self):
69 # Create volume type
70 name = data_utils.rand_name("volume-type")
71 volume_type = self.os_admin.volume_types_v2_client.create_volume_type(
72 name=name)['volume_type']
73
74 # Create CG
75 cg_name = data_utils.rand_name('CG')
76 create_consistencygroup = (
77 self.consistencygroups_adm_client.create_consistencygroup)
78 cg = create_consistencygroup(volume_type['id'],
79 name=cg_name)['consistencygroup']
80 vol_name = data_utils.rand_name("volume")
81 params = {'name': vol_name,
82 'volume_type': volume_type['id'],
83 'consistencygroup_id': cg['id'],
84 'size': CONF.volume.volume_size}
85
86 # Create volume
87 volume = self.admin_volume_client.create_volume(**params)['volume']
88
89 waiters.wait_for_volume_resource_status(self.admin_volume_client,
90 volume['id'], 'available')
91 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
92 cg['id'], 'available')
93 self.assertEqual(cg_name, cg['name'])
94
95 # Get a given CG
96 cg = self.consistencygroups_adm_client.show_consistencygroup(
97 cg['id'])['consistencygroup']
98 self.assertEqual(cg_name, cg['name'])
99
100 # Get all CGs with detail
101 cgs = self.consistencygroups_adm_client.list_consistencygroups(
102 detail=True)['consistencygroups']
103 self.assertIn((cg['name'], cg['id']),
104 [(m['name'], m['id']) for m in cgs])
105
106 # Clean up
107 self._delete_consistencygroup(cg['id'])
108 self.os_admin.volume_types_v2_client.delete_volume_type(
109 volume_type['id'])
110
111 @decorators.idempotent_id('2134dd52-f333-4456-bb05-6cb0f009a44f')
112 def test_consistencygroup_cgsnapshot_create_delete(self):
113 # Create volume type
114 name = data_utils.rand_name("volume-type")
115 volume_type = self.admin_volume_types_client.create_volume_type(
116 name=name)['volume_type']
117
118 # Create CG
119 cg_name = data_utils.rand_name('CG')
120 create_consistencygroup = (
121 self.consistencygroups_adm_client.create_consistencygroup)
122 cg = create_consistencygroup(volume_type['id'],
123 name=cg_name)['consistencygroup']
124 vol_name = data_utils.rand_name("volume")
125 params = {'name': vol_name,
126 'volume_type': volume_type['id'],
127 'consistencygroup_id': cg['id'],
128 'size': CONF.volume.volume_size}
129
130 # Create volume
131 volume = self.admin_volume_client.create_volume(**params)['volume']
132 waiters.wait_for_volume_resource_status(self.admin_volume_client,
133 volume['id'], 'available')
134 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
135 cg['id'], 'available')
136 self.assertEqual(cg_name, cg['name'])
137
138 # Create cgsnapshot
139 cgsnapshot_name = data_utils.rand_name('cgsnapshot')
140 create_cgsnapshot = (
141 self.consistencygroups_adm_client.create_cgsnapshot)
142 cgsnapshot = create_cgsnapshot(cg['id'],
143 name=cgsnapshot_name)['cgsnapshot']
144 snapshots = self.os_admin.snapshots_v2_client.list_snapshots(
145 detail=True)['snapshots']
146 for snap in snapshots:
147 if volume['id'] == snap['volume_id']:
148 waiters.wait_for_volume_resource_status(
149 self.os_admin.snapshots_v2_client,
150 snap['id'], 'available')
151 self.consistencygroups_adm_client.wait_for_cgsnapshot_status(
152 cgsnapshot['id'], 'available')
153 self.assertEqual(cgsnapshot_name, cgsnapshot['name'])
154
155 # Get a given CG snapshot
156 cgsnapshot = self.consistencygroups_adm_client.show_cgsnapshot(
157 cgsnapshot['id'])['cgsnapshot']
158 self.assertEqual(cgsnapshot_name, cgsnapshot['name'])
159
160 # Get all CG snapshots with detail
161 cgsnapshots = self.consistencygroups_adm_client.list_cgsnapshots(
162 detail=True)['cgsnapshots']
163 self.assertIn((cgsnapshot['name'], cgsnapshot['id']),
164 [(m['name'], m['id']) for m in cgsnapshots])
165
166 # Clean up
167 self._delete_cgsnapshot(cgsnapshot['id'], cg['id'])
168 self._delete_consistencygroup(cg['id'])
169 self.admin_volume_types_client.delete_volume_type(volume_type['id'])
170
171 @decorators.idempotent_id('3a6a5525-25ca-4a6c-aac4-cac6fa8f5b43')
172 def test_create_consistencygroup_from_cgsnapshot(self):
173 # Create volume type
174 name = data_utils.rand_name("volume-type")
175 volume_type = self.admin_volume_types_client.create_volume_type(
176 name=name)['volume_type']
177
178 # Create CG
179 cg_name = data_utils.rand_name('CG')
180 create_consistencygroup = (
181 self.consistencygroups_adm_client.create_consistencygroup)
182 cg = create_consistencygroup(volume_type['id'],
183 name=cg_name)['consistencygroup']
184 vol_name = data_utils.rand_name("volume")
185 params = {'name': vol_name,
186 'volume_type': volume_type['id'],
187 'consistencygroup_id': cg['id'],
188 'size': CONF.volume.volume_size}
189
190 # Create volume
191 volume = self.admin_volume_client.create_volume(**params)['volume']
192 waiters.wait_for_volume_resource_status(self.admin_volume_client,
193 volume['id'], 'available')
194 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
195 cg['id'], 'available')
196 self.assertEqual(cg_name, cg['name'])
197
198 # Create cgsnapshot
199 cgsnapshot_name = data_utils.rand_name('cgsnapshot')
200 create_cgsnapshot = (
201 self.consistencygroups_adm_client.create_cgsnapshot)
202 cgsnapshot = create_cgsnapshot(cg['id'],
203 name=cgsnapshot_name)['cgsnapshot']
204 snapshots = self.snapshots_client.list_snapshots(
205 detail=True)['snapshots']
206 for snap in snapshots:
207 if volume['id'] == snap['volume_id']:
208 waiters.wait_for_volume_resource_status(
209 self.os_admin.snapshots_v2_client, snap['id'], 'available')
210 self.consistencygroups_adm_client.wait_for_cgsnapshot_status(
211 cgsnapshot['id'], 'available')
212 self.assertEqual(cgsnapshot_name, cgsnapshot['name'])
213
214 # Create CG from CG snapshot
215 cg_name2 = data_utils.rand_name('CG_from_snap')
216 create_consistencygroup2 = (
217 self.consistencygroups_adm_client.create_consistencygroup_from_src)
218 cg2 = create_consistencygroup2(cgsnapshot_id=cgsnapshot['id'],
219 name=cg_name2)['consistencygroup']
220 vols = self.admin_volume_client.list_volumes(
221 detail=True)['volumes']
222 for vol in vols:
223 if vol['consistencygroup_id'] == cg2['id']:
224 waiters.wait_for_volume_resource_status(
225 self.admin_volume_client, vol['id'], 'available')
226 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
227 cg2['id'], 'available')
228 self.assertEqual(cg_name2, cg2['name'])
229
230 # Clean up
231 self._delete_consistencygroup(cg2['id'])
232 self._delete_cgsnapshot(cgsnapshot['id'], cg['id'])
233 self._delete_consistencygroup(cg['id'])
234 self.admin_volume_types_client.delete_volume_type(volume_type['id'])
235
236 @decorators.idempotent_id('556121ae-de9c-4342-9897-e54260447a19')
237 def test_create_consistencygroup_from_consistencygroup(self):
238 # Create volume type
239 name = data_utils.rand_name("volume-type")
240 volume_type = self.admin_volume_types_client.create_volume_type(
241 name=name)['volume_type']
242
243 # Create CG
244 cg_name = data_utils.rand_name('CG')
245 create_consistencygroup = (
246 self.consistencygroups_adm_client.create_consistencygroup)
247 cg = create_consistencygroup(volume_type['id'],
248 name=cg_name)['consistencygroup']
249 vol_name = data_utils.rand_name("volume")
250 params = {'name': vol_name,
251 'volume_type': volume_type['id'],
252 'consistencygroup_id': cg['id'],
253 'size': CONF.volume.volume_size}
254
255 # Create volume
256 volume = self.admin_volume_client.create_volume(**params)['volume']
257 waiters.wait_for_volume_resource_status(self.admin_volume_client,
258 volume['id'], 'available')
259 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
260 cg['id'], 'available')
261 self.assertEqual(cg_name, cg['name'])
262
263 # Create CG from CG
264 cg_name2 = data_utils.rand_name('CG_from_cg')
265 create_consistencygroup2 = (
266 self.consistencygroups_adm_client.create_consistencygroup_from_src)
267 cg2 = create_consistencygroup2(source_cgid=cg['id'],
268 name=cg_name2)['consistencygroup']
269 vols = self.admin_volume_client.list_volumes(
270 detail=True)['volumes']
271 for vol in vols:
272 if vol['consistencygroup_id'] == cg2['id']:
273 waiters.wait_for_volume_resource_status(
274 self.admin_volume_client, vol['id'], 'available')
275 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
276 cg2['id'], 'available')
277 self.assertEqual(cg_name2, cg2['name'])
278
279 # Clean up
280 self._delete_consistencygroup(cg2['id'])
281 self._delete_consistencygroup(cg['id'])
282 self.admin_volume_types_client.delete_volume_type(volume_type['id'])
+0
-130
cinder/tests/tempest/api/volume/test_volume_backup.py less more
0 # Copyright (c) 2016 Mirantis Inc.
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.common.utils import data_utils
18 from tempest.lib import decorators
19
20 from cinder.tests.tempest.api.volume import base
21
22 CONF = config.CONF
23
24
25 class VolumesBackupsTest(base.BaseVolumeTest):
26
27 @classmethod
28 def skip_checks(cls):
29 super(VolumesBackupsTest, cls).skip_checks()
30 if not CONF.volume_feature_enabled.backup:
31 raise cls.skipException("Cinder backup feature disabled")
32
33 @decorators.idempotent_id('885410c6-cd1d-452c-a409-7c32b7e0be15')
34 def test_volume_snapshot_backup(self):
35 """Create backup from snapshot."""
36 volume = self.create_volume()
37 # Create snapshot
38 snapshot = self.create_snapshot(volume['id'])
39 # Create backup
40 backup = self.create_backup(
41 volume_id=volume['id'],
42 snapshot_id=snapshot['id'])
43 # Get a given backup
44 backup = self.backups_client.show_backup(
45 backup['id'])['backup']
46 waiters.wait_for_volume_resource_status(
47 self.backups_client,
48 backup['id'], 'available')
49 self.assertEqual(volume['id'], backup['volume_id'])
50 self.assertEqual(snapshot['id'], backup['snapshot_id'])
51
52 self.snapshots_client.delete_snapshot(snapshot['id'])
53 self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
54
55 self.volumes_client.delete_volume(volume['id'])
56 self.volumes_client.wait_for_resource_deletion(volume['id'])
57
58 @decorators.idempotent_id('b5d837b0-7066-455d-88fc-4a721a899306')
59 def test_backup_create_and_restore_to_an_existing_volume(self):
60 """Test backup create and restore to an existing volume."""
61 # Create volume
62 src_vol = self.create_volume()
63 self.addCleanup(self.volumes_client.delete_volume,
64 src_vol['id'])
65 # Create backup
66 backup = self.backups_client.create_backup(
67 volume_id=src_vol['id'])['backup']
68 self.addCleanup(self.backups_client.delete_backup, backup['id'])
69 waiters.wait_for_volume_resource_status(
70 self.backups_client,
71 backup['id'], 'available')
72 # Restore to existing volume
73 restore = self.backups_client.restore_backup(
74 backup_id=backup['id'],
75 volume_id=src_vol['id'])['restore']
76 waiters.wait_for_volume_resource_status(
77 self.backups_client,
78 backup['id'], 'available')
79 waiters.wait_for_volume_resource_status(
80 self.volumes_client,
81 src_vol['id'], 'available')
82 self.assertEqual(src_vol['id'], restore['volume_id'])
83 self.assertEqual(backup['id'], restore['backup_id'])
84
85 @decorators.idempotent_id('c810fe2c-cb40-43ab-96aa-471b74516a98')
86 def test_incremental_backup(self):
87 """Test create incremental backup."""
88 # Create volume from image
89 volume = self.create_volume(size=CONF.volume.volume_size,
90 imageRef=CONF.compute.image_ref)
91 self.addCleanup(self.volumes_client.delete_volume,
92 volume['id'])
93
94 # Create backup
95 backup = self.backups_client.create_backup(
96 volume_id=volume['id'])['backup']
97 waiters.wait_for_volume_resource_status(self.backups_client,
98 backup['id'], 'available')
99 # Create a server
100 bd_map = [{'volume_id': volume['id'],
101 'delete_on_termination': '0'}]
102
103 server_name = data_utils.rand_name('instance')
104 server = self.create_server(
105 name=server_name,
106 block_device_mapping=bd_map,
107 wait_until='ACTIVE')
108
109 # Delete VM
110 self.os_primary.servers_client.delete_server(server['id'])
111 # Create incremental backup
112 waiters.wait_for_volume_resource_status(self.volumes_client,
113 volume['id'], 'available')
114 backup_incr = self.backups_client.create_backup(
115 volume_id=volume['id'],
116 incremental=True)['backup']
117
118 waiters.wait_for_volume_resource_status(self.backups_client,
119 backup_incr['id'],
120 'available')
121
122 is_incremental = self.backups_client.show_backup(
123 backup_incr['id'])['backup']['is_incremental']
124 self.assertTrue(is_incremental)
125
126 self.backups_client.delete_backup(backup_incr['id'])
127 self.backups_client.wait_for_resource_deletion(backup_incr['id'])
128 self.backups_client.delete_backup(backup['id'])
129 self.backups_client.wait_for_resource_deletion(backup['id'])
+0
-83
cinder/tests/tempest/api/volume/test_volume_revert.py less more
0 # Copyright (c) 2017 Huawei.
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
19 from cinder.tests.tempest.api.volume import base
20 from cinder.tests.tempest import cinder_clients
21
22 CONF = config.CONF
23
24
25 class VolumeRevertTests(base.BaseVolumeTest):
26 min_microversion = '3.40'
27
28 @classmethod
29 def skip_checks(cls):
30 super(VolumeRevertTests, cls).skip_checks()
31 if not CONF.volume_feature_enabled.volume_revert:
32 raise cls.skipException("Cinder volume revert feature disabled")
33
34 @classmethod
35 def setup_clients(cls):
36 cls._api_version = 3
37 super(VolumeRevertTests, cls).setup_clients()
38
39 manager = cinder_clients.Manager(cls.os_primary)
40 cls.volume_revert_client = manager.volume_revert_client
41
42 def setUp(self):
43 super(VolumeRevertTests, self).setUp()
44 # Create volume
45 self.volume = self.create_volume(size=1)
46 # Create snapshot
47 self.snapshot = self.create_snapshot(self.volume['id'])
48
49 @decorators.idempotent_id('87b7dcb7-4950-4a3a-802c-ece55491846d')
50 def test_volume_revert_to_snapshot(self):
51 """Test revert to snapshot"""
52 # Revert to snapshot
53 self.volume_revert_client.revert_to_snapshot(self.volume,
54 self.snapshot['id'])
55 waiters.wait_for_volume_resource_status(
56 self.volumes_client,
57 self.volume['id'], 'available')
58 waiters.wait_for_volume_resource_status(
59 self.snapshots_client,
60 self.snapshot['id'], 'available')
61 volume = self.volumes_client.show_volume(self.volume['id'])['volume']
62
63 self.assertEqual(1, volume['size'])
64
65 @decorators.idempotent_id('4e8b0788-87fe-430d-be7a-444d7f8e0347')
66 def test_volume_revert_to_snapshot_after_extended(self):
67 """Test revert to snapshot after extended"""
68 # Extend the volume
69 self.volumes_client.extend_volume(self.volume['id'], new_size=2)
70 waiters.wait_for_volume_resource_status(self.volumes_client,
71 self.volume['id'], 'available')
72 # Revert to snapshot
73 self.volume_revert_client.revert_to_snapshot(self.volume,
74 self.snapshot['id'])
75 waiters.wait_for_volume_resource_status(
76 self.volumes_client,
77 self.volume['id'], 'available')
78 waiters.wait_for_volume_resource_status(
79 self.snapshots_client,
80 self.snapshot['id'], 'available')
81 volume = self.volumes_client.show_volume(self.volume['id'])['volume']
82 self.assertEqual(2, volume['size'])
+0
-64
cinder/tests/tempest/api/volume/test_volume_unicode.py less more
0 # -*- coding: utf-8 -*-
1 # Copyright 2016 Red Hat, Inc.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 from tempest.common import waiters
17 from tempest import config
18 from tempest.lib.common.utils import data_utils
19 from tempest.lib.common.utils import test_utils
20
21 from cinder.tests.tempest.api.volume import base
22
23 CONF = config.CONF
24
25
26 class CinderUnicodeTest(base.BaseVolumeTest):
27
28 @classmethod
29 def resource_setup(cls):
30 super(CinderUnicodeTest, cls).resource_setup()
31
32 # Stick to three-byte unicode here, since four+ byte
33 # chars require utf8mb4 database support which may not
34 # be configured.
35 cls.volume_name = u"CinderUnicodeTest塵㼗‽"
36 cls.volume = cls.create_volume_with_args(name=cls.volume_name)
37
38 @classmethod
39 def create_volume_with_args(cls, **kwargs):
40 if 'name' not in kwargs:
41 kwargs['name'] = data_utils.rand_name('Volume')
42
43 kwargs['size'] = CONF.volume.volume_size
44
45 volume = cls.volumes_client.create_volume(**kwargs)['volume']
46 cls.addClassResourceCleanup(
47 cls.volumes_client.wait_for_resource_deletion, volume['id'])
48 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
49 cls.volumes_client.delete_volume,
50 volume['id'])
51 waiters.wait_for_volume_resource_status(cls.volumes_client,
52 volume['id'],
53 'available')
54
55 return volume
56
57 def test_create_delete_unicode_volume_name(self):
58 """Create a volume with a unicode name and view it."""
59
60 result = self.volumes_client.show_volume(self.volume['id'])
61 fetched_volume = result['volume']
62 self.assertEqual(fetched_volume['name'],
63 self.volume_name)
+0
-40
cinder/tests/tempest/cinder_clients.py less more
0 # Copyright (c) 2016 Pure Storage, Inc.
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 import config
16
17 from cinder.tests.tempest.services import consistencygroups_client
18 from cinder.tests.tempest.services import volume_revert_client
19
20 CONF = config.CONF
21
22
23 class Manager(object):
24 def __init__(self, base_manager):
25 params = {
26 'service': CONF.volume.catalog_type,
27 'region': CONF.volume.region or CONF.identity.region,
28 'endpoint_type': CONF.volume.endpoint_type,
29 'build_interval': CONF.volume.build_interval,
30 'build_timeout': CONF.volume.build_timeout
31 }
32 params.update(base_manager.default_params)
33 auth_provider = base_manager.auth_provider
34
35 self.consistencygroups_adm_client = (
36 consistencygroups_client.ConsistencyGroupsClient(auth_provider,
37 **params))
38 self.volume_revert_client = (
39 volume_revert_client.VolumeRevertClient(auth_provider, **params))
+0
-25
cinder/tests/tempest/config.py less more
0 # Copyright 2016
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 oslo_config import cfg
16
17 cinder_option = [
18 cfg.BoolOpt('consistency_group',
19 default=False,
20 help='Enable to run Cinder volume consistency group tests'),
21 cfg.BoolOpt('volume_revert',
22 default=False,
23 help='Enable to run Cinder volume revert tests'),
24 ]
+0
-43
cinder/tests/tempest/plugin.py less more
0 # Copyright 2015
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 import cinder
16 import os
17
18 from cinder.tests.tempest import config as project_config
19
20 from tempest import config
21 from tempest.test_discover import plugins
22
23
24 class CinderTempestPlugin(plugins.TempestPlugin):
25 def load_tests(self):
26 base_path = os.path.split(os.path.dirname(
27 os.path.abspath(cinder.__file__)))[0]
28 test_dir = "cinder/tests/tempest"
29 full_test_dir = os.path.join(base_path, test_dir)
30 return full_test_dir, base_path
31
32 def register_opts(self, conf):
33 config.register_opt_group(
34 conf, config.volume_feature_group,
35 project_config.cinder_option
36 )
37
38 def get_opt_lists(self):
39 return [
40 (config.volume_feature_group.name,
41 project_config.cinder_option),
42 ]
+0
-0
cinder/tests/tempest/scenario/__init__.py less more
(Empty file)
+0
-0
cinder/tests/tempest/services/__init__.py less more
(Empty file)
+0
-193
cinder/tests/tempest/services/consistencygroups_client.py less more
0 # Copyright (C) 2015 EMC Corporation.
1 # Copyright (C) 2016 Pure Storage, Inc.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 import time
17
18 from oslo_serialization import jsonutils as json
19 from six.moves import http_client
20 from tempest import exceptions
21 from tempest.lib.common import rest_client
22 from tempest.lib import exceptions as lib_exc
23
24
25 class ConsistencyGroupsClient(rest_client.RestClient):
26 """Client class to send CRUD Volume ConsistencyGroup API requests"""
27
28 def __init__(self, auth_provider, service, region, **kwargs):
29 super(ConsistencyGroupsClient, self).__init__(
30 auth_provider, service, region, **kwargs)
31
32 def create_consistencygroup(self, volume_types, **kwargs):
33 """Creates a consistency group."""
34 post_body = {'volume_types': volume_types}
35 if kwargs.get('availability_zone'):
36 post_body['availability_zone'] = kwargs.get('availability_zone')
37 if kwargs.get('name'):
38 post_body['name'] = kwargs.get('name')
39 if kwargs.get('description'):
40 post_body['description'] = kwargs.get('description')
41 post_body = json.dumps({'consistencygroup': post_body})
42 resp, body = self.post('consistencygroups', post_body)
43 body = json.loads(body)
44 self.expected_success(http_client.ACCEPTED, resp.status)
45 return rest_client.ResponseBody(resp, body)
46
47 def create_consistencygroup_from_src(self, **kwargs):
48 """Creates a consistency group from source."""
49 post_body = {}
50 if kwargs.get('cgsnapshot_id'):
51 post_body['cgsnapshot_id'] = kwargs.get('cgsnapshot_id')
52 if kwargs.get('source_cgid'):
53 post_body['source_cgid'] = kwargs.get('source_cgid')
54 if kwargs.get('name'):
55 post_body['name'] = kwargs.get('name')
56 if kwargs.get('description'):
57 post_body['description'] = kwargs.get('description')
58 post_body = json.dumps({'consistencygroup-from-src': post_body})
59 resp, body = self.post('consistencygroups/create_from_src', post_body)
60 body = json.loads(body)
61 self.expected_success(http_client.ACCEPTED, resp.status)
62 return rest_client.ResponseBody(resp, body)
63
64 def delete_consistencygroup(self, cg_id):
65 """Delete a consistency group."""
66 post_body = {'force': True}
67 post_body = json.dumps({'consistencygroup': post_body})
68 resp, body = self.post('consistencygroups/%s/delete' % cg_id,
69 post_body)
70 self.expected_success(http_client.ACCEPTED, resp.status)
71 return rest_client.ResponseBody(resp, body)
72
73 def show_consistencygroup(self, cg_id):
74 """Returns the details of a single consistency group."""
75 url = "consistencygroups/%s" % str(cg_id)
76 resp, body = self.get(url)
77 body = json.loads(body)
78 self.expected_success(http_client.OK, resp.status)
79 return rest_client.ResponseBody(resp, body)
80
81 def list_consistencygroups(self, detail=False):
82 """Information for all the tenant's consistency groups."""
83 url = "consistencygroups"
84 if detail:
85 url += "/detail"
86 resp, body = self.get(url)
87 body = json.loads(body)
88 self.expected_success(http_client.OK, resp.status)
89 return rest_client.ResponseBody(resp, body)
90
91 def create_cgsnapshot(self, consistencygroup_id, **kwargs):
92 """Creates a consistency group snapshot."""
93 post_body = {'consistencygroup_id': consistencygroup_id}
94 if kwargs.get('name'):
95 post_body['name'] = kwargs.get('name')
96 if kwargs.get('description'):
97 post_body['description'] = kwargs.get('description')
98 post_body = json.dumps({'cgsnapshot': post_body})
99 resp, body = self.post('cgsnapshots', post_body)
100 body = json.loads(body)
101 self.expected_success(http_client.ACCEPTED, resp.status)
102 return rest_client.ResponseBody(resp, body)
103
104 def delete_cgsnapshot(self, cgsnapshot_id):
105 """Delete a consistency group snapshot."""
106 resp, body = self.delete('cgsnapshots/%s' % (str(cgsnapshot_id)))
107 self.expected_success(http_client.ACCEPTED, resp.status)
108 return rest_client.ResponseBody(resp, body)
109
110 def show_cgsnapshot(self, cgsnapshot_id):
111 """Returns the details of a single consistency group snapshot."""
112 url = "cgsnapshots/%s" % str(cgsnapshot_id)
113 resp, body = self.get(url)
114 body = json.loads(body)
115 self.expected_success(http_client.OK, resp.status)
116 return rest_client.ResponseBody(resp, body)
117
118 def list_cgsnapshots(self, detail=False):
119 """Information for all the tenant's consistency group snapshotss."""
120 url = "cgsnapshots"
121 if detail:
122 url += "/detail"
123 resp, body = self.get(url)
124 body = json.loads(body)
125 self.expected_success(http_client.OK, resp.status)
126 return rest_client.ResponseBody(resp, body)
127
128 def wait_for_consistencygroup_status(self, cg_id, status):
129 """Waits for a consistency group to reach a given status."""
130 body = self.show_consistencygroup(cg_id)['consistencygroup']
131 cg_status = body['status']
132 start = int(time.time())
133
134 while cg_status != status:
135 time.sleep(self.build_interval)
136 body = self.show_consistencygroup(cg_id)['consistencygroup']
137 cg_status = body['status']
138 if cg_status == 'error':
139 raise exceptions.ConsistencyGroupException(cg_id=cg_id)
140
141 if int(time.time()) - start >= self.build_timeout:
142 message = ('Consistency group %s failed to reach %s status '
143 '(current %s) within the required time (%s s).' %
144 (cg_id, status, cg_status,
145 self.build_timeout))
146 raise exceptions.TimeoutException(message)
147
148 def wait_for_consistencygroup_deletion(self, cg_id):
149 """Waits for consistency group deletion"""
150 start_time = int(time.time())
151 while True:
152 try:
153 self.show_consistencygroup(cg_id)
154 except lib_exc.NotFound:
155 return
156 if int(time.time()) - start_time >= self.build_timeout:
157 raise exceptions.TimeoutException
158 time.sleep(self.build_interval)
159
160 def wait_for_cgsnapshot_status(self, cgsnapshot_id, status):
161 """Waits for a consistency group snapshot to reach a given status."""
162 body = self.show_cgsnapshot(cgsnapshot_id)['cgsnapshot']
163 cgsnapshot_status = body['status']
164 start = int(time.time())
165
166 while cgsnapshot_status != status:
167 time.sleep(self.build_interval)
168 body = self.show_cgsnapshot(cgsnapshot_id)['cgsnapshot']
169 cgsnapshot_status = body['status']
170 if cgsnapshot_status == 'error':
171 raise exceptions.ConsistencyGroupSnapshotException(
172 cgsnapshot_id=cgsnapshot_id)
173
174 if int(time.time()) - start >= self.build_timeout:
175 message = ('Consistency group snapshot %s failed to reach '
176 '%s status (current %s) within the required time '
177 '(%s s).' %
178 (cgsnapshot_id, status, cgsnapshot_status,
179 self.build_timeout))
180 raise exceptions.TimeoutException(message)
181
182 def wait_for_cgsnapshot_deletion(self, cgsnapshot_id):
183 """Waits for consistency group snapshot deletion"""
184 start_time = int(time.time())
185 while True:
186 try:
187 self.show_cgsnapshot(cgsnapshot_id)
188 except lib_exc.NotFound:
189 return
190 if int(time.time()) - start_time >= self.build_timeout:
191 raise exceptions.TimeoutException
192 time.sleep(self.build_interval)
+0
-34
cinder/tests/tempest/services/volume_revert_client.py less more
0 # Copyright (C) 2017 Huawei.
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 oslo_serialization import jsonutils as json
16 from tempest.lib.common import rest_client
17 from tempest.lib.services.volume import base_client
18
19
20 class VolumeRevertClient(base_client.BaseClient):
21 """Client class to send revert to snapshot action API request"""
22
23 def __init__(self, auth_provider, service, region, **kwargs):
24 super(VolumeRevertClient, self).__init__(
25 auth_provider, service, region, **kwargs)
26
27 def revert_to_snapshot(self, volume, snapshot_id):
28 """Revert a volume to snapshot."""
29 post_body = {'snapshot_id': snapshot_id}
30 post_body = json.dumps({'revert': post_body})
31 resp, body = self.post('volumes/%s/action' % volume['id'],
32 post_body)
33 return rest_client.ResponseBody(resp, body)
0 # Copyright 2017 NEC Corporation.
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.api.volume import api_microversion_fixture
16 from tempest.common import compute
17 from tempest.common import waiters
18 from tempest import config
19 from tempest.lib.common import api_version_utils
20 from tempest.lib.common.utils import data_utils
21 from tempest.lib.common.utils import test_utils
22 from tempest.lib import exceptions
23 from tempest import test
24
25 CONF = config.CONF
26
27
28 class BaseVolumeTest(api_version_utils.BaseMicroversionTest,
29 test.BaseTestCase):
30 """Base test case class for all Cinder API tests."""
31
32 _api_version = 2
33 credentials = ['primary']
34
35 @classmethod
36 def skip_checks(cls):
37 super(BaseVolumeTest, cls).skip_checks()
38
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 if cls._api_version == 2:
43 if not CONF.volume_feature_enabled.api_v2:
44 msg = "Volume API v2 is disabled"
45 raise cls.skipException(msg)
46 elif cls._api_version == 3:
47 if not CONF.volume_feature_enabled.api_v3:
48 msg = "Volume API v3 is disabled"
49 raise cls.skipException(msg)
50 else:
51 msg = ("Invalid Cinder API version (%s)" % cls._api_version)
52 raise exceptions.InvalidConfiguration(msg)
53
54 api_version_utils.check_skip_with_microversion(
55 cls.min_microversion, cls.max_microversion,
56 CONF.volume.min_microversion, CONF.volume.max_microversion)
57
58 @classmethod
59 def setup_clients(cls):
60 super(BaseVolumeTest, cls).setup_clients()
61 if cls._api_version == 3:
62 cls.backups_client = cls.os_primary.backups_v3_client
63 cls.volumes_client = cls.os_primary.volumes_v3_client
64 else:
65 cls.backups_client = cls.os_primary.backups_v2_client
66 cls.volumes_client = cls.os_primary.volumes_v2_client
67
68 cls.snapshots_client = cls.os_primary.snapshots_v2_client
69
70 @classmethod
71 def setup_credentials(cls):
72 cls.set_network_resources()
73 super(BaseVolumeTest, cls).setup_credentials()
74
75 def setUp(self):
76 super(BaseVolumeTest, self).setUp()
77 self.useFixture(api_microversion_fixture.APIMicroversionFixture(
78 self.request_microversion))
79
80 @classmethod
81 def resource_setup(cls):
82 super(BaseVolumeTest, cls).resource_setup()
83 cls.request_microversion = (
84 api_version_utils.select_request_microversion(
85 cls.min_microversion,
86 CONF.volume.min_microversion))
87
88 @classmethod
89 def create_volume(cls, wait_until='available', **kwargs):
90 """Wrapper utility that returns a test volume.
91
92 :param wait_until: wait till volume status.
93 """
94 if 'size' not in kwargs:
95 kwargs['size'] = CONF.volume.volume_size
96
97 if 'imageRef' in kwargs:
98 image = cls.os_primary.image_client_v2.show_image(
99 kwargs['imageRef'])
100 min_disk = image['min_disk']
101 kwargs['size'] = max(kwargs['size'], min_disk)
102
103 if 'name' not in kwargs:
104 name = data_utils.rand_name(cls.__name__ + '-Volume')
105 kwargs['name'] = name
106
107 volume = cls.volumes_client.create_volume(**kwargs)['volume']
108 cls.addClassResourceCleanup(
109 cls.volumes_client.wait_for_resource_deletion, volume['id'])
110 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
111 cls.volumes_client.delete_volume,
112 volume['id'])
113 waiters.wait_for_volume_resource_status(cls.volumes_client,
114 volume['id'], wait_until)
115 return volume
116
117 @classmethod
118 def create_snapshot(cls, volume_id=1, **kwargs):
119 """Wrapper utility that returns a test snapshot."""
120 if 'name' not in kwargs:
121 name = data_utils.rand_name(cls.__name__ + '-Snapshot')
122 kwargs['name'] = name
123
124 snapshot = cls.snapshots_client.create_snapshot(
125 volume_id=volume_id, **kwargs)['snapshot']
126 cls.addClassResourceCleanup(
127 cls.snapshots_client.wait_for_resource_deletion, snapshot['id'])
128 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
129 cls.snapshots_client.delete_snapshot,
130 snapshot['id'])
131 waiters.wait_for_volume_resource_status(cls.snapshots_client,
132 snapshot['id'], 'available')
133 return snapshot
134
135 def create_backup(self, volume_id, backup_client=None, **kwargs):
136 """Wrapper utility that returns a test backup."""
137 if backup_client is None:
138 backup_client = self.backups_client
139 if 'name' not in kwargs:
140 name = data_utils.rand_name(self.__class__.__name__ + '-Backup')
141 kwargs['name'] = name
142
143 backup = backup_client.create_backup(
144 volume_id=volume_id, **kwargs)['backup']
145 self.addCleanup(backup_client.delete_backup, backup['id'])
146 waiters.wait_for_volume_resource_status(backup_client, backup['id'],
147 'available')
148 return backup
149
150 def create_server(self, wait_until='ACTIVE', **kwargs):
151 name = kwargs.pop(
152 'name',
153 data_utils.rand_name(self.__class__.__name__ + '-instance'))
154
155 tenant_network = self.get_tenant_network()
156 body, _ = compute.create_test_server(
157 self.os_primary,
158 tenant_network=tenant_network,
159 name=name,
160 wait_until=wait_until,
161 **kwargs)
162
163 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
164 waiters.wait_for_server_termination,
165 self.os_primary.servers_client, body['id'])
166 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
167 self.os_primary.servers_client.delete_server,
168 body['id'])
169 return body
0 # Copyright (C) 2015 EMC Corporation.
1 # Copyright (C) 2016 Pure Storage, Inc.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 from tempest.common import waiters
17 from tempest import config
18 from tempest.lib.common.utils import data_utils
19 from tempest.lib import decorators
20
21 from cinder_tempest_plugin.api.volume import base
22 from cinder_tempest_plugin import cinder_clients
23
24 CONF = config.CONF
25
26
27 class ConsistencyGroupsV2Test(base.BaseVolumeTest):
28 @classmethod
29 def setup_clients(cls):
30 cls._api_version = 2
31 super(ConsistencyGroupsV2Test, cls).setup_clients()
32 cls.admin_volume_client = cls.os_admin.volumes_v2_client
33
34 manager = cinder_clients.Manager(cls.os_admin)
35 cls.consistencygroups_adm_client = manager.consistencygroups_adm_client
36
37 @classmethod
38 def skip_checks(cls):
39 super(ConsistencyGroupsV2Test, cls).skip_checks()
40 if not CONF.volume_feature_enabled.consistency_group:
41 raise cls.skipException("Cinder consistency group "
42 "feature disabled")
43
44 def _delete_consistencygroup(self, cg_id):
45 self.consistencygroups_adm_client.delete_consistencygroup(cg_id)
46 vols = self.admin_volume_client.list_volumes(detail=True)['volumes']
47 for vol in vols:
48 if vol['consistencygroup_id'] == cg_id:
49 self.admin_volume_client.wait_for_resource_deletion(vol['id'])
50 self.consistencygroups_adm_client.wait_for_consistencygroup_deletion(
51 cg_id)
52
53 def _delete_cgsnapshot(self, cgsnapshot_id, cg_id):
54 self.consistencygroups_adm_client.delete_cgsnapshot(cgsnapshot_id)
55 vols = self.admin_volume_client.list_volumes(detail=True)['volumes']
56 snapshots = self.os_admin.snapshots_v2_client.list_snapshots(
57 detail=True)['snapshots']
58 for vol in vols:
59 for snap in snapshots:
60 if (vol['consistencygroup_id'] == cg_id and
61 vol['id'] == snap['volume_id']):
62 (self.snapshots_client.
63 wait_for_resource_deletion(snap['id']))
64 self.consistencygroups_adm_client.wait_for_cgsnapshot_deletion(
65 cgsnapshot_id)
66
67 @decorators.idempotent_id('3fe776ba-ec1f-4e6c-8d78-4b14c3a7fc44')
68 def test_consistencygroup_create_delete(self):
69 # Create volume type
70 name = data_utils.rand_name("volume-type")
71 volume_type = self.os_admin.volume_types_v2_client.create_volume_type(
72 name=name)['volume_type']
73
74 # Create CG
75 cg_name = data_utils.rand_name('CG')
76 create_consistencygroup = (
77 self.consistencygroups_adm_client.create_consistencygroup)
78 cg = create_consistencygroup(volume_type['id'],
79 name=cg_name)['consistencygroup']
80 vol_name = data_utils.rand_name("volume")
81 params = {'name': vol_name,
82 'volume_type': volume_type['id'],
83 'consistencygroup_id': cg['id'],
84 'size': CONF.volume.volume_size}
85
86 # Create volume
87 volume = self.admin_volume_client.create_volume(**params)['volume']
88
89 waiters.wait_for_volume_resource_status(self.admin_volume_client,
90 volume['id'], 'available')
91 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
92 cg['id'], 'available')
93 self.assertEqual(cg_name, cg['name'])
94
95 # Get a given CG
96 cg = self.consistencygroups_adm_client.show_consistencygroup(
97 cg['id'])['consistencygroup']
98 self.assertEqual(cg_name, cg['name'])
99
100 # Get all CGs with detail
101 cgs = self.consistencygroups_adm_client.list_consistencygroups(
102 detail=True)['consistencygroups']
103 self.assertIn((cg['name'], cg['id']),
104 [(m['name'], m['id']) for m in cgs])
105
106 # Clean up
107 self._delete_consistencygroup(cg['id'])
108 self.os_admin.volume_types_v2_client.delete_volume_type(
109 volume_type['id'])
110
111 @decorators.idempotent_id('2134dd52-f333-4456-bb05-6cb0f009a44f')
112 def test_consistencygroup_cgsnapshot_create_delete(self):
113 # Create volume type
114 name = data_utils.rand_name("volume-type")
115 volume_type = self.admin_volume_types_client.create_volume_type(
116 name=name)['volume_type']
117
118 # Create CG
119 cg_name = data_utils.rand_name('CG')
120 create_consistencygroup = (
121 self.consistencygroups_adm_client.create_consistencygroup)
122 cg = create_consistencygroup(volume_type['id'],
123 name=cg_name)['consistencygroup']
124 vol_name = data_utils.rand_name("volume")
125 params = {'name': vol_name,
126 'volume_type': volume_type['id'],
127 'consistencygroup_id': cg['id'],
128 'size': CONF.volume.volume_size}
129
130 # Create volume
131 volume = self.admin_volume_client.create_volume(**params)['volume']
132 waiters.wait_for_volume_resource_status(self.admin_volume_client,
133 volume['id'], 'available')
134 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
135 cg['id'], 'available')
136 self.assertEqual(cg_name, cg['name'])
137
138 # Create cgsnapshot
139 cgsnapshot_name = data_utils.rand_name('cgsnapshot')
140 create_cgsnapshot = (
141 self.consistencygroups_adm_client.create_cgsnapshot)
142 cgsnapshot = create_cgsnapshot(cg['id'],
143 name=cgsnapshot_name)['cgsnapshot']
144 snapshots = self.os_admin.snapshots_v2_client.list_snapshots(
145 detail=True)['snapshots']
146 for snap in snapshots:
147 if volume['id'] == snap['volume_id']:
148 waiters.wait_for_volume_resource_status(
149 self.os_admin.snapshots_v2_client,
150 snap['id'], 'available')
151 self.consistencygroups_adm_client.wait_for_cgsnapshot_status(
152 cgsnapshot['id'], 'available')
153 self.assertEqual(cgsnapshot_name, cgsnapshot['name'])
154
155 # Get a given CG snapshot
156 cgsnapshot = self.consistencygroups_adm_client.show_cgsnapshot(
157 cgsnapshot['id'])['cgsnapshot']
158 self.assertEqual(cgsnapshot_name, cgsnapshot['name'])
159
160 # Get all CG snapshots with detail
161 cgsnapshots = self.consistencygroups_adm_client.list_cgsnapshots(
162 detail=True)['cgsnapshots']
163 self.assertIn((cgsnapshot['name'], cgsnapshot['id']),
164 [(m['name'], m['id']) for m in cgsnapshots])
165
166 # Clean up
167 self._delete_cgsnapshot(cgsnapshot['id'], cg['id'])
168 self._delete_consistencygroup(cg['id'])
169 self.admin_volume_types_client.delete_volume_type(volume_type['id'])
170
171 @decorators.idempotent_id('3a6a5525-25ca-4a6c-aac4-cac6fa8f5b43')
172 def test_create_consistencygroup_from_cgsnapshot(self):
173 # Create volume type
174 name = data_utils.rand_name("volume-type")
175 volume_type = self.admin_volume_types_client.create_volume_type(
176 name=name)['volume_type']
177
178 # Create CG
179 cg_name = data_utils.rand_name('CG')
180 create_consistencygroup = (
181 self.consistencygroups_adm_client.create_consistencygroup)
182 cg = create_consistencygroup(volume_type['id'],
183 name=cg_name)['consistencygroup']
184 vol_name = data_utils.rand_name("volume")
185 params = {'name': vol_name,
186 'volume_type': volume_type['id'],
187 'consistencygroup_id': cg['id'],
188 'size': CONF.volume.volume_size}
189
190 # Create volume
191 volume = self.admin_volume_client.create_volume(**params)['volume']
192 waiters.wait_for_volume_resource_status(self.admin_volume_client,
193 volume['id'], 'available')
194 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
195 cg['id'], 'available')
196 self.assertEqual(cg_name, cg['name'])
197
198 # Create cgsnapshot
199 cgsnapshot_name = data_utils.rand_name('cgsnapshot')
200 create_cgsnapshot = (
201 self.consistencygroups_adm_client.create_cgsnapshot)
202 cgsnapshot = create_cgsnapshot(cg['id'],
203 name=cgsnapshot_name)['cgsnapshot']
204 snapshots = self.snapshots_client.list_snapshots(
205 detail=True)['snapshots']
206 for snap in snapshots:
207 if volume['id'] == snap['volume_id']:
208 waiters.wait_for_volume_resource_status(
209 self.os_admin.snapshots_v2_client, snap['id'], 'available')
210 self.consistencygroups_adm_client.wait_for_cgsnapshot_status(
211 cgsnapshot['id'], 'available')
212 self.assertEqual(cgsnapshot_name, cgsnapshot['name'])
213
214 # Create CG from CG snapshot
215 cg_name2 = data_utils.rand_name('CG_from_snap')
216 create_consistencygroup2 = (
217 self.consistencygroups_adm_client.create_consistencygroup_from_src)
218 cg2 = create_consistencygroup2(cgsnapshot_id=cgsnapshot['id'],
219 name=cg_name2)['consistencygroup']
220 vols = self.admin_volume_client.list_volumes(
221 detail=True)['volumes']
222 for vol in vols:
223 if vol['consistencygroup_id'] == cg2['id']:
224 waiters.wait_for_volume_resource_status(
225 self.admin_volume_client, vol['id'], 'available')
226 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
227 cg2['id'], 'available')
228 self.assertEqual(cg_name2, cg2['name'])
229
230 # Clean up
231 self._delete_consistencygroup(cg2['id'])
232 self._delete_cgsnapshot(cgsnapshot['id'], cg['id'])
233 self._delete_consistencygroup(cg['id'])
234 self.admin_volume_types_client.delete_volume_type(volume_type['id'])
235
236 @decorators.idempotent_id('556121ae-de9c-4342-9897-e54260447a19')
237 def test_create_consistencygroup_from_consistencygroup(self):
238 # Create volume type
239 name = data_utils.rand_name("volume-type")
240 volume_type = self.admin_volume_types_client.create_volume_type(
241 name=name)['volume_type']
242
243 # Create CG
244 cg_name = data_utils.rand_name('CG')
245 create_consistencygroup = (
246 self.consistencygroups_adm_client.create_consistencygroup)
247 cg = create_consistencygroup(volume_type['id'],
248 name=cg_name)['consistencygroup']
249 vol_name = data_utils.rand_name("volume")
250 params = {'name': vol_name,
251 'volume_type': volume_type['id'],
252 'consistencygroup_id': cg['id'],
253 'size': CONF.volume.volume_size}
254
255 # Create volume
256 volume = self.admin_volume_client.create_volume(**params)['volume']
257 waiters.wait_for_volume_resource_status(self.admin_volume_client,
258 volume['id'], 'available')
259 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
260 cg['id'], 'available')
261 self.assertEqual(cg_name, cg['name'])
262
263 # Create CG from CG
264 cg_name2 = data_utils.rand_name('CG_from_cg')
265 create_consistencygroup2 = (
266 self.consistencygroups_adm_client.create_consistencygroup_from_src)
267 cg2 = create_consistencygroup2(source_cgid=cg['id'],
268 name=cg_name2)['consistencygroup']
269 vols = self.admin_volume_client.list_volumes(
270 detail=True)['volumes']
271 for vol in vols:
272 if vol['consistencygroup_id'] == cg2['id']:
273 waiters.wait_for_volume_resource_status(
274 self.admin_volume_client, vol['id'], 'available')
275 self.consistencygroups_adm_client.wait_for_consistencygroup_status(
276 cg2['id'], 'available')
277 self.assertEqual(cg_name2, cg2['name'])
278
279 # Clean up
280 self._delete_consistencygroup(cg2['id'])
281 self._delete_consistencygroup(cg['id'])
282 self.admin_volume_types_client.delete_volume_type(volume_type['id'])
0 # Copyright (c) 2016 Mirantis Inc.
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.common.utils import data_utils
18 from tempest.lib import decorators
19
20 from cinder_tempest_plugin.api.volume import base
21
22 CONF = config.CONF
23
24
25 class VolumesBackupsTest(base.BaseVolumeTest):
26
27 @classmethod
28 def skip_checks(cls):
29 super(VolumesBackupsTest, cls).skip_checks()
30 if not CONF.volume_feature_enabled.backup:
31 raise cls.skipException("Cinder backup feature disabled")
32
33 @decorators.idempotent_id('885410c6-cd1d-452c-a409-7c32b7e0be15')
34 def test_volume_snapshot_backup(self):
35 """Create backup from snapshot."""
36 volume = self.create_volume()
37 # Create snapshot
38 snapshot = self.create_snapshot(volume['id'])
39 # Create backup
40 backup = self.create_backup(
41 volume_id=volume['id'],
42 snapshot_id=snapshot['id'])
43 # Get a given backup
44 backup = self.backups_client.show_backup(
45 backup['id'])['backup']
46 waiters.wait_for_volume_resource_status(
47 self.backups_client,
48 backup['id'], 'available')
49 self.assertEqual(volume['id'], backup['volume_id'])
50 self.assertEqual(snapshot['id'], backup['snapshot_id'])
51
52 self.snapshots_client.delete_snapshot(snapshot['id'])
53 self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
54
55 self.volumes_client.delete_volume(volume['id'])
56 self.volumes_client.wait_for_resource_deletion(volume['id'])
57
58 @decorators.idempotent_id('b5d837b0-7066-455d-88fc-4a721a899306')
59 def test_backup_create_and_restore_to_an_existing_volume(self):
60 """Test backup create and restore to an existing volume."""
61 # Create volume
62 src_vol = self.create_volume()
63 self.addCleanup(self.volumes_client.delete_volume,
64 src_vol['id'])
65 # Create backup
66 backup = self.backups_client.create_backup(
67 volume_id=src_vol['id'])['backup']
68 self.addCleanup(self.backups_client.delete_backup, backup['id'])
69 waiters.wait_for_volume_resource_status(
70 self.backups_client,
71 backup['id'], 'available')
72 # Restore to existing volume
73 restore = self.backups_client.restore_backup(
74 backup_id=backup['id'],
75 volume_id=src_vol['id'])['restore']
76 waiters.wait_for_volume_resource_status(
77 self.backups_client,
78 backup['id'], 'available')
79 waiters.wait_for_volume_resource_status(
80 self.volumes_client,
81 src_vol['id'], 'available')
82 self.assertEqual(src_vol['id'], restore['volume_id'])
83 self.assertEqual(backup['id'], restore['backup_id'])
84
85 @decorators.idempotent_id('c810fe2c-cb40-43ab-96aa-471b74516a98')
86 def test_incremental_backup(self):
87 """Test create incremental backup."""
88 # Create volume from image
89 volume = self.create_volume(size=CONF.volume.volume_size,
90 imageRef=CONF.compute.image_ref)
91 self.addCleanup(self.volumes_client.delete_volume,
92 volume['id'])
93
94 # Create backup
95 backup = self.backups_client.create_backup(
96 volume_id=volume['id'])['backup']
97 waiters.wait_for_volume_resource_status(self.backups_client,
98 backup['id'], 'available')
99 # Create a server
100 bd_map = [{'volume_id': volume['id'],
101 'delete_on_termination': '0'}]
102
103 server_name = data_utils.rand_name('instance')
104 server = self.create_server(
105 name=server_name,
106 block_device_mapping=bd_map,
107 wait_until='ACTIVE')
108
109 # Delete VM
110 self.os_primary.servers_client.delete_server(server['id'])
111 # Create incremental backup
112 waiters.wait_for_volume_resource_status(self.volumes_client,
113 volume['id'], 'available')
114 backup_incr = self.backups_client.create_backup(
115 volume_id=volume['id'],
116 incremental=True)['backup']
117
118 waiters.wait_for_volume_resource_status(self.backups_client,
119 backup_incr['id'],
120 'available')
121
122 is_incremental = self.backups_client.show_backup(
123 backup_incr['id'])['backup']['is_incremental']
124 self.assertTrue(is_incremental)
125
126 self.backups_client.delete_backup(backup_incr['id'])
127 self.backups_client.wait_for_resource_deletion(backup_incr['id'])
128 self.backups_client.delete_backup(backup['id'])
129 self.backups_client.wait_for_resource_deletion(backup['id'])
0 # Copyright (c) 2017 Huawei.
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
19 from cinder_tempest_plugin.api.volume import base
20 from cinder_tempest_plugin import cinder_clients
21
22 CONF = config.CONF
23
24
25 class VolumeRevertTests(base.BaseVolumeTest):
26 min_microversion = '3.40'
27
28 @classmethod
29 def skip_checks(cls):
30 super(VolumeRevertTests, cls).skip_checks()
31 if not CONF.volume_feature_enabled.volume_revert:
32 raise cls.skipException("Cinder volume revert feature disabled")
33
34 @classmethod
35 def setup_clients(cls):
36 cls._api_version = 3
37 super(VolumeRevertTests, cls).setup_clients()
38
39 manager = cinder_clients.Manager(cls.os_primary)
40 cls.volume_revert_client = manager.volume_revert_client
41
42 def setUp(self):
43 super(VolumeRevertTests, self).setUp()
44 # Create volume
45 self.volume = self.create_volume(size=1)
46 # Create snapshot
47 self.snapshot = self.create_snapshot(self.volume['id'])
48
49 @decorators.idempotent_id('87b7dcb7-4950-4a3a-802c-ece55491846d')
50 def test_volume_revert_to_snapshot(self):
51 """Test revert to snapshot"""
52 # Revert to snapshot
53 self.volume_revert_client.revert_to_snapshot(self.volume,
54 self.snapshot['id'])
55 waiters.wait_for_volume_resource_status(
56 self.volumes_client,
57 self.volume['id'], 'available')
58 waiters.wait_for_volume_resource_status(
59 self.snapshots_client,
60 self.snapshot['id'], 'available')
61 volume = self.volumes_client.show_volume(self.volume['id'])['volume']
62
63 self.assertEqual(1, volume['size'])
64
65 @decorators.idempotent_id('4e8b0788-87fe-430d-be7a-444d7f8e0347')
66 def test_volume_revert_to_snapshot_after_extended(self):
67 """Test revert to snapshot after extended"""
68 # Extend the volume
69 self.volumes_client.extend_volume(self.volume['id'], new_size=2)
70 waiters.wait_for_volume_resource_status(self.volumes_client,
71 self.volume['id'], 'available')
72 # Revert to snapshot
73 self.volume_revert_client.revert_to_snapshot(self.volume,
74 self.snapshot['id'])
75 waiters.wait_for_volume_resource_status(
76 self.volumes_client,
77 self.volume['id'], 'available')
78 waiters.wait_for_volume_resource_status(
79 self.snapshots_client,
80 self.snapshot['id'], 'available')
81 volume = self.volumes_client.show_volume(self.volume['id'])['volume']
82 self.assertEqual(2, volume['size'])
0 # -*- coding: utf-8 -*-
1 # Copyright 2016 Red Hat, Inc.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 from tempest.common import waiters
17 from tempest import config
18 from tempest.lib.common.utils import data_utils
19 from tempest.lib.common.utils import test_utils
20
21 from cinder_tempest_plugin.api.volume import base
22
23 CONF = config.CONF
24
25
26 class CinderUnicodeTest(base.BaseVolumeTest):
27
28 @classmethod
29 def resource_setup(cls):
30 super(CinderUnicodeTest, cls).resource_setup()
31
32 # Stick to three-byte unicode here, since four+ byte
33 # chars require utf8mb4 database support which may not
34 # be configured.
35 cls.volume_name = u"CinderUnicodeTest塵㼗‽"
36 cls.volume = cls.create_volume_with_args(name=cls.volume_name)
37
38 @classmethod
39 def create_volume_with_args(cls, **kwargs):
40 if 'name' not in kwargs:
41 kwargs['name'] = data_utils.rand_name('Volume')
42
43 kwargs['size'] = CONF.volume.volume_size
44
45 volume = cls.volumes_client.create_volume(**kwargs)['volume']
46 cls.addClassResourceCleanup(
47 cls.volumes_client.wait_for_resource_deletion, volume['id'])
48 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
49 cls.volumes_client.delete_volume,
50 volume['id'])
51 waiters.wait_for_volume_resource_status(cls.volumes_client,
52 volume['id'],
53 'available')
54
55 return volume
56
57 def test_create_delete_unicode_volume_name(self):
58 """Create a volume with a unicode name and view it."""
59
60 result = self.volumes_client.show_volume(self.volume['id'])
61 fetched_volume = result['volume']
62 self.assertEqual(fetched_volume['name'],
63 self.volume_name)
0 # Copyright (c) 2016 Pure Storage, Inc.
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 import config
16
17 from cinder_tempest_plugin.services import consistencygroups_client
18 from cinder_tempest_plugin.services import volume_revert_client
19
20 CONF = config.CONF
21
22
23 class Manager(object):
24 def __init__(self, base_manager):
25 params = {
26 'service': CONF.volume.catalog_type,
27 'region': CONF.volume.region or CONF.identity.region,
28 'endpoint_type': CONF.volume.endpoint_type,
29 'build_interval': CONF.volume.build_interval,
30 'build_timeout': CONF.volume.build_timeout
31 }
32 params.update(base_manager.default_params)
33 auth_provider = base_manager.auth_provider
34
35 self.consistencygroups_adm_client = (
36 consistencygroups_client.ConsistencyGroupsClient(auth_provider,
37 **params))
38 self.volume_revert_client = (
39 volume_revert_client.VolumeRevertClient(auth_provider, **params))
0 # Copyright 2016
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 oslo_config import cfg
16
17 cinder_option = [
18 cfg.BoolOpt('consistency_group',
19 default=False,
20 help='Enable to run Cinder volume consistency group tests'),
21 cfg.BoolOpt('volume_revert',
22 default=False,
23 help='Enable to run Cinder volume revert tests'),
24 ]
0 # Copyright 2015
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 import cinder
16 import os
17
18 from cinder_tempest_plugin import config as project_config
19
20 from tempest import config
21 from tempest.test_discover import plugins
22
23
24 class CinderTempestPlugin(plugins.TempestPlugin):
25 def load_tests(self):
26 base_path = os.path.split(os.path.dirname(
27 os.path.abspath(cinder.__file__)))[0]
28 test_dir = "cinder_tempest_plugin"
29 full_test_dir = os.path.join(base_path, test_dir)
30 return full_test_dir, base_path
31
32 def register_opts(self, conf):
33 config.register_opt_group(
34 conf, config.volume_feature_group,
35 project_config.cinder_option
36 )
37
38 def get_opt_lists(self):
39 return [
40 (config.volume_feature_group.name,
41 project_config.cinder_option),
42 ]
0 # Copyright (C) 2015 EMC Corporation.
1 # Copyright (C) 2016 Pure Storage, Inc.
2 # All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 import time
17
18 from oslo_serialization import jsonutils as json
19 from six.moves import http_client
20 from tempest import exceptions
21 from tempest.lib.common import rest_client
22 from tempest.lib import exceptions as lib_exc
23
24
25 class ConsistencyGroupsClient(rest_client.RestClient):
26 """Client class to send CRUD Volume ConsistencyGroup API requests"""
27
28 def __init__(self, auth_provider, service, region, **kwargs):
29 super(ConsistencyGroupsClient, self).__init__(
30 auth_provider, service, region, **kwargs)
31
32 def create_consistencygroup(self, volume_types, **kwargs):
33 """Creates a consistency group."""
34 post_body = {'volume_types': volume_types}
35 if kwargs.get('availability_zone'):
36 post_body['availability_zone'] = kwargs.get('availability_zone')
37 if kwargs.get('name'):
38 post_body['name'] = kwargs.get('name')
39 if kwargs.get('description'):
40 post_body['description'] = kwargs.get('description')
41 post_body = json.dumps({'consistencygroup': post_body})
42 resp, body = self.post('consistencygroups', post_body)
43 body = json.loads(body)
44 self.expected_success(http_client.ACCEPTED, resp.status)
45 return rest_client.ResponseBody(resp, body)
46
47 def create_consistencygroup_from_src(self, **kwargs):
48 """Creates a consistency group from source."""
49 post_body = {}
50 if kwargs.get('cgsnapshot_id'):
51 post_body['cgsnapshot_id'] = kwargs.get('cgsnapshot_id')
52 if kwargs.get('source_cgid'):
53 post_body['source_cgid'] = kwargs.get('source_cgid')
54 if kwargs.get('name'):
55 post_body['name'] = kwargs.get('name')
56 if kwargs.get('description'):
57 post_body['description'] = kwargs.get('description')
58 post_body = json.dumps({'consistencygroup-from-src': post_body})
59 resp, body = self.post('consistencygroups/create_from_src', post_body)
60 body = json.loads(body)
61 self.expected_success(http_client.ACCEPTED, resp.status)
62 return rest_client.ResponseBody(resp, body)
63
64 def delete_consistencygroup(self, cg_id):
65 """Delete a consistency group."""
66 post_body = {'force': True}
67 post_body = json.dumps({'consistencygroup': post_body})
68 resp, body = self.post('consistencygroups/%s/delete' % cg_id,
69 post_body)
70 self.expected_success(http_client.ACCEPTED, resp.status)
71 return rest_client.ResponseBody(resp, body)
72
73 def show_consistencygroup(self, cg_id):
74 """Returns the details of a single consistency group."""
75 url = "consistencygroups/%s" % str(cg_id)
76 resp, body = self.get(url)
77 body = json.loads(body)
78 self.expected_success(http_client.OK, resp.status)
79 return rest_client.ResponseBody(resp, body)
80
81 def list_consistencygroups(self, detail=False):
82 """Information for all the tenant's consistency groups."""
83 url = "consistencygroups"
84 if detail:
85 url += "/detail"
86 resp, body = self.get(url)
87 body = json.loads(body)
88 self.expected_success(http_client.OK, resp.status)
89 return rest_client.ResponseBody(resp, body)
90
91 def create_cgsnapshot(self, consistencygroup_id, **kwargs):
92 """Creates a consistency group snapshot."""
93 post_body = {'consistencygroup_id': consistencygroup_id}
94 if kwargs.get('name'):
95 post_body['name'] = kwargs.get('name')
96 if kwargs.get('description'):
97 post_body['description'] = kwargs.get('description')
98 post_body = json.dumps({'cgsnapshot': post_body})
99 resp, body = self.post('cgsnapshots', post_body)
100 body = json.loads(body)
101 self.expected_success(http_client.ACCEPTED, resp.status)
102 return rest_client.ResponseBody(resp, body)
103
104 def delete_cgsnapshot(self, cgsnapshot_id):
105 """Delete a consistency group snapshot."""
106 resp, body = self.delete('cgsnapshots/%s' % (str(cgsnapshot_id)))
107 self.expected_success(http_client.ACCEPTED, resp.status)
108 return rest_client.ResponseBody(resp, body)
109
110 def show_cgsnapshot(self, cgsnapshot_id):
111 """Returns the details of a single consistency group snapshot."""
112 url = "cgsnapshots/%s" % str(cgsnapshot_id)
113 resp, body = self.get(url)
114 body = json.loads(body)
115 self.expected_success(http_client.OK, resp.status)
116 return rest_client.ResponseBody(resp, body)
117
118 def list_cgsnapshots(self, detail=False):
119 """Information for all the tenant's consistency group snapshotss."""
120 url = "cgsnapshots"
121 if detail:
122 url += "/detail"
123 resp, body = self.get(url)
124 body = json.loads(body)
125 self.expected_success(http_client.OK, resp.status)
126 return rest_client.ResponseBody(resp, body)
127
128 def wait_for_consistencygroup_status(self, cg_id, status):
129 """Waits for a consistency group to reach a given status."""
130 body = self.show_consistencygroup(cg_id)['consistencygroup']
131 cg_status = body['status']
132 start = int(time.time())
133
134 while cg_status != status:
135 time.sleep(self.build_interval)
136 body = self.show_consistencygroup(cg_id)['consistencygroup']
137 cg_status = body['status']
138 if cg_status == 'error':
139 raise exceptions.ConsistencyGroupException(cg_id=cg_id)
140
141 if int(time.time()) - start >= self.build_timeout:
142 message = ('Consistency group %s failed to reach %s status '
143 '(current %s) within the required time (%s s).' %
144 (cg_id, status, cg_status,
145 self.build_timeout))
146 raise exceptions.TimeoutException(message)
147
148 def wait_for_consistencygroup_deletion(self, cg_id):
149 """Waits for consistency group deletion"""
150 start_time = int(time.time())
151 while True:
152 try:
153 self.show_consistencygroup(cg_id)
154 except lib_exc.NotFound:
155 return
156 if int(time.time()) - start_time >= self.build_timeout:
157 raise exceptions.TimeoutException
158 time.sleep(self.build_interval)
159
160 def wait_for_cgsnapshot_status(self, cgsnapshot_id, status):
161 """Waits for a consistency group snapshot to reach a given status."""
162 body = self.show_cgsnapshot(cgsnapshot_id)['cgsnapshot']
163 cgsnapshot_status = body['status']
164 start = int(time.time())
165
166 while cgsnapshot_status != status:
167 time.sleep(self.build_interval)
168 body = self.show_cgsnapshot(cgsnapshot_id)['cgsnapshot']
169 cgsnapshot_status = body['status']
170 if cgsnapshot_status == 'error':
171 raise exceptions.ConsistencyGroupSnapshotException(
172 cgsnapshot_id=cgsnapshot_id)
173
174 if int(time.time()) - start >= self.build_timeout:
175 message = ('Consistency group snapshot %s failed to reach '
176 '%s status (current %s) within the required time '
177 '(%s s).' %
178 (cgsnapshot_id, status, cgsnapshot_status,
179 self.build_timeout))
180 raise exceptions.TimeoutException(message)
181
182 def wait_for_cgsnapshot_deletion(self, cgsnapshot_id):
183 """Waits for consistency group snapshot deletion"""
184 start_time = int(time.time())
185 while True:
186 try:
187 self.show_cgsnapshot(cgsnapshot_id)
188 except lib_exc.NotFound:
189 return
190 if int(time.time()) - start_time >= self.build_timeout:
191 raise exceptions.TimeoutException
192 time.sleep(self.build_interval)
0 # Copyright (C) 2017 Huawei.
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 oslo_serialization import jsonutils as json
16 from tempest.lib.common import rest_client
17 from tempest.lib.services.volume import base_client
18
19
20 class VolumeRevertClient(base_client.BaseClient):
21 """Client class to send revert to snapshot action API request"""
22
23 def __init__(self, auth_provider, service, region, **kwargs):
24 super(VolumeRevertClient, self).__init__(
25 auth_provider, service, region, **kwargs)
26
27 def revert_to_snapshot(self, volume, snapshot_id):
28 """Revert a volume to snapshot."""
29 post_body = {'snapshot_id': snapshot_id}
30 post_body = json.dumps({'revert': post_body})
31 resp, body = self.post('volumes/%s/action' % volume['id'],
32 post_body)
33 return rest_client.ResponseBody(resp, body)
4646
4747 [entry_points]
4848 tempest.test_plugins =
49 cinder_tests = cinder.tests.tempest.plugin:CinderTempestPlugin
49 cinder_tests = cinder_tempest_plugin.plugin:CinderTempestPlugin