blob: 2810440484bbd790278c1303f5f8bebee00af790 [file] [log] [blame]
lkuchlan9dea88e2016-06-07 17:12:01 +03001# 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
lkuchlana7fd37a2017-02-12 16:25:54 +020016from testtools import matchers
17
lkuchlan9dea88e2016-06-07 17:12:01 +030018from tempest.api.volume import base
Andrea Frittolicd368412017-08-14 21:37:56 +010019from tempest.common import utils
lkuchlan9dea88e2016-06-07 17:12:01 +030020from tempest.common import waiters
21from tempest import config
Ken'ichi Ohmichief1c1ce2017-03-10 11:07:10 -080022from tempest.lib.common.utils import data_utils
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -080023from tempest.lib import decorators
lkuchlan9dea88e2016-06-07 17:12:01 +030024
25CONF = config.CONF
26
27
Ken'ichi Ohmichie8afb8c2017-03-27 11:25:37 -070028class VolumesBackupsTest(base.BaseVolumeTest):
zhufl067bcd02020-08-14 16:56:34 +080029 """Test volumes backup"""
lkuchlan9dea88e2016-06-07 17:12:01 +030030
Dan Smith27487862023-05-05 06:52:44 -070031 create_default_network = True
32
lkuchlan9dea88e2016-06-07 17:12:01 +030033 @classmethod
34 def skip_checks(cls):
Ken'ichi Ohmichie8afb8c2017-03-27 11:25:37 -070035 super(VolumesBackupsTest, cls).skip_checks()
lkuchlan9dea88e2016-06-07 17:12:01 +030036 if not CONF.volume_feature_enabled.backup:
37 raise cls.skipException("Cinder backup feature disabled")
38
lkuchlanc6e88a62016-12-08 17:12:31 +020039 def restore_backup(self, backup_id):
40 # Restore a backup
41 restored_volume = self.backups_client.restore_backup(
42 backup_id)['restore']
43
44 # Delete backup
zhuflcae2a752017-11-24 12:43:43 +080045 self.addCleanup(self.delete_volume, self.volumes_client,
lkuchlanc6e88a62016-12-08 17:12:31 +020046 restored_volume['volume_id'])
47 self.assertEqual(backup_id, restored_volume['backup_id'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020048 waiters.wait_for_volume_resource_status(self.backups_client,
49 backup_id, 'available')
50 waiters.wait_for_volume_resource_status(self.volumes_client,
51 restored_volume['volume_id'],
52 'available')
lkuchlanc6e88a62016-12-08 17:12:31 +020053 return restored_volume
54
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -080055 @decorators.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
lkuchlanf8a66682016-06-16 14:49:19 +030056 def test_volume_backup_create_get_detailed_list_restore_delete(self):
zhufl067bcd02020-08-14 16:56:34 +080057 """Test create/get/list/restore/delete volume backup
58
59 1. Create volume1 with metadata
60 2. Create backup1 from volume1
61 3. Show backup1
62 4. List backups with detail
63 5. Restore backup1
64 6. Verify backup1 has been restored successfully with the metadata
65 of volume1
66 """
lkuchlana7fd37a2017-02-12 16:25:54 +020067 # Create a volume with metadata
68 metadata = {"vol-meta1": "value1",
69 "vol-meta2": "value2",
70 "vol-meta3": "value3"}
71 volume = self.create_volume(metadata=metadata)
zhuflcae2a752017-11-24 12:43:43 +080072 self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
lkuchlana7fd37a2017-02-12 16:25:54 +020073
74 # Create a backup
Lukáš Piwowarski553d91b2023-09-21 11:14:24 +020075 kwargs = {}
76 kwargs["name"] = data_utils.rand_name(
Martin Kopec213d0a42023-11-30 10:28:14 +010077 prefix=CONF.resource_name_prefix,
78 name=self.__class__.__name__ + '-Backup')
79 kwargs["description"] = data_utils.rand_name(
80 prefix=CONF.resource_name_prefix,
81 name="backup-description")
Lukáš Piwowarski553d91b2023-09-21 11:14:24 +020082 if CONF.volume.backup_driver == "swift":
83 kwargs["container"] = data_utils.rand_name(
Martin Kopec213d0a42023-11-30 10:28:14 +010084 prefix=CONF.resource_name_prefix,
85 name=self.__class__.__name__ + '-Backup-container')
Lukáš Piwowarski553d91b2023-09-21 11:14:24 +020086 backup = self.create_backup(volume_id=volume['id'], **kwargs)
87 self.assertEqual(kwargs["name"], backup['name'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020088 waiters.wait_for_volume_resource_status(self.volumes_client,
89 volume['id'], 'available')
lkuchlanf8a66682016-06-16 14:49:19 +030090
91 # Get a given backup
92 backup = self.backups_client.show_backup(backup['id'])['backup']
Lukáš Piwowarski553d91b2023-09-21 11:14:24 +020093 self.assertEqual(kwargs["name"], backup['name'])
94 self.assertEqual(kwargs["description"], backup['description'])
95 if CONF.volume.backup_driver == "swift":
96 self.assertEqual(kwargs["container"], backup['container'])
lkuchlanf8a66682016-06-16 14:49:19 +030097
98 # Get all backups with detail
zhufl93a047f2018-11-08 14:35:49 +080099 backups = self.backups_client.list_backups(detail=True)['backups']
lkuchlanf8a66682016-06-16 14:49:19 +0300100 self.assertIn((backup['name'], backup['id']),
101 [(m['name'], m['id']) for m in backups])
102
lkuchlana7fd37a2017-02-12 16:25:54 +0200103 restored_volume = self.restore_backup(backup['id'])
104
105 restored_volume_metadata = self.volumes_client.show_volume(
106 restored_volume['volume_id'])['volume']['metadata']
107
zhufl067bcd02020-08-14 16:56:34 +0800108 # Verify the backup has been restored successfully
lkuchlana7fd37a2017-02-12 16:25:54 +0200109 # with the metadata of the source volume.
110 self.assertThat(restored_volume_metadata.items(),
111 matchers.ContainsAll(metadata.items()))
lkuchlanf8a66682016-06-16 14:49:19 +0300112
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -0800113 @decorators.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
Andrea Frittolicd368412017-08-14 21:37:56 +0100114 @utils.services('compute')
lkuchlan9dea88e2016-06-07 17:12:01 +0300115 def test_backup_create_attached_volume(self):
116 """Test backup create using force flag.
117
118 Cinder allows to create a volume backup, whether the volume status
119 is "available" or "in-use".
120 """
121 # Create a server
Dan Smith7fc42802023-07-21 10:59:18 -0700122 volume = self.create_volume(wait_until=False)
zhuflcae2a752017-11-24 12:43:43 +0800123 self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
Dan Smith27487862023-05-05 06:52:44 -0700124 validation_resources = self.get_test_validation_resources(
125 self.os_primary)
126 server = self.create_server(wait_until='SSHABLE',
127 validation_resources=validation_resources,
128 validatable=True)
lkuchlan9dea88e2016-06-07 17:12:01 +0300129 # Attach volume to instance
Dan Smith7fc42802023-07-21 10:59:18 -0700130 waiters.wait_for_volume_resource_status(self.volumes_client,
131 volume['id'], 'available')
lkuchland818ef32017-01-11 12:22:22 +0200132 self.attach_volume(server['id'], volume['id'])
lkuchlan9dea88e2016-06-07 17:12:01 +0300133 # Create backup using force flag
zhuflc6ce5392016-08-17 14:34:37 +0800134 backup_name = data_utils.rand_name(
Martin Kopec213d0a42023-11-30 10:28:14 +0100135 prefix=CONF.resource_name_prefix,
136 name=self.__class__.__name__ + '-Backup')
lkuchlana2beb492016-08-17 12:42:44 +0300137 backup = self.create_backup(volume_id=volume['id'],
138 name=backup_name, force=True)
jeremy.zhangd1be5012018-06-06 17:25:39 +0800139 waiters.wait_for_volume_resource_status(self.volumes_client,
140 volume['id'], 'in-use')
lkuchlan9dea88e2016-06-07 17:12:01 +0300141 self.assertEqual(backup_name, backup['name'])
142
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -0800143 @decorators.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
Andrea Frittolicd368412017-08-14 21:37:56 +0100144 @utils.services('image')
lkuchlanc6e88a62016-12-08 17:12:31 +0200145 def test_bootable_volume_backup_and_restore(self):
zhufl067bcd02020-08-14 16:56:34 +0800146 """Test backuping and restoring a bootable volume
147
148 1. Create volume1 from image
149 2. Create backup1 from volume1
150 3. Restore backup1
151 4. Verify the restored backup volume is bootable
152 """
lkuchlanc6e88a62016-12-08 17:12:31 +0200153 # Create volume from image
154 img_uuid = CONF.compute.image_ref
155 volume = self.create_volume(imageRef=img_uuid)
156
157 volume_details = self.volumes_client.show_volume(
158 volume['id'])['volume']
lkuchlana7aac722018-05-13 13:44:40 +0300159 self.assertTrue(volume_details['bootable'])
lkuchlanc6e88a62016-12-08 17:12:31 +0200160
161 # Create a backup
162 backup = self.create_backup(volume_id=volume['id'])
jeremy.zhangd1be5012018-06-06 17:25:39 +0800163 waiters.wait_for_volume_resource_status(self.volumes_client,
164 volume['id'], 'available')
lkuchlanc6e88a62016-12-08 17:12:31 +0200165
166 # Restore the backup
167 restored_volume_id = self.restore_backup(backup['id'])['volume_id']
168
169 # Verify the restored backup volume is bootable
170 restored_volume_info = self.volumes_client.show_volume(
171 restored_volume_id)['volume']
172
lkuchlana7aac722018-05-13 13:44:40 +0300173 self.assertTrue(restored_volume_info['bootable'])
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800174
175
176class VolumesBackupsV39Test(base.BaseVolumeTest):
zhufl067bcd02020-08-14 16:56:34 +0800177 """Test volumes backup with volume microversion greater than 3.8"""
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800178
Sophie Huangd458bf32021-10-12 17:08:41 +0000179 volume_min_microversion = '3.9'
180 volume_max_microversion = 'latest'
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800181
182 @classmethod
183 def skip_checks(cls):
184 super(VolumesBackupsV39Test, cls).skip_checks()
185 if not CONF.volume_feature_enabled.backup:
186 raise cls.skipException("Cinder backup feature disabled")
187
188 @decorators.idempotent_id('9b374cbc-be5f-4d37-8848-7efb8a873dcc')
189 def test_update_backup(self):
zhufl067bcd02020-08-14 16:56:34 +0800190 """Test updating backup's name and description"""
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800191 # Create volume and backup
192 volume = self.create_volume()
193 backup = self.create_backup(volume_id=volume['id'])
jeremy.zhangd1be5012018-06-06 17:25:39 +0800194 waiters.wait_for_volume_resource_status(self.volumes_client,
195 volume['id'], 'available')
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800196
197 # Update backup and assert response body for update_backup method
198 update_kwargs = {
Martin Kopec213d0a42023-11-30 10:28:14 +0100199 'name': data_utils.rand_name(
200 prefix=CONF.resource_name_prefix,
201 name=self.__class__.__name__ + '-Backup'),
202 'description': data_utils.rand_name(
203 prefix=CONF.resource_name_prefix,
204 name="volume-backup-description")
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800205 }
206 update_backup = self.backups_client.update_backup(
207 backup['id'], **update_kwargs)['backup']
208 self.assertEqual(backup['id'], update_backup['id'])
209 self.assertEqual(update_kwargs['name'], update_backup['name'])
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800210
211 # Assert response body for show_backup method
212 retrieved_backup = self.backups_client.show_backup(
213 backup['id'])['backup']
214 for key in update_kwargs:
215 self.assertEqual(update_kwargs[key], retrieved_backup[key])