blob: 138d1206ea9775ce25e72eab86650251e65e27bd [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
Jaesang Leee4dc8fb2017-03-25 01:19:58 +000016import testtools
lkuchlana7fd37a2017-02-12 16:25:54 +020017from testtools import matchers
18
lkuchlan9dea88e2016-06-07 17:12:01 +030019from tempest.api.volume import base
Andrea Frittolicd368412017-08-14 21:37:56 +010020from tempest.common import utils
lkuchlan9dea88e2016-06-07 17:12:01 +030021from tempest.common import waiters
22from tempest import config
Ken'ichi Ohmichief1c1ce2017-03-10 11:07:10 -080023from tempest.lib.common.utils import data_utils
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -080024from tempest.lib import decorators
lkuchlan9dea88e2016-06-07 17:12:01 +030025
26CONF = config.CONF
27
28
Ken'ichi Ohmichie8afb8c2017-03-27 11:25:37 -070029class VolumesBackupsTest(base.BaseVolumeTest):
zhufl067bcd02020-08-14 16:56:34 +080030 """Test volumes backup"""
lkuchlan9dea88e2016-06-07 17:12:01 +030031
32 @classmethod
33 def skip_checks(cls):
Ken'ichi Ohmichie8afb8c2017-03-27 11:25:37 -070034 super(VolumesBackupsTest, cls).skip_checks()
lkuchlan9dea88e2016-06-07 17:12:01 +030035 if not CONF.volume_feature_enabled.backup:
36 raise cls.skipException("Cinder backup feature disabled")
37
lkuchlanc6e88a62016-12-08 17:12:31 +020038 def restore_backup(self, backup_id):
39 # Restore a backup
40 restored_volume = self.backups_client.restore_backup(
41 backup_id)['restore']
42
43 # Delete backup
zhuflcae2a752017-11-24 12:43:43 +080044 self.addCleanup(self.delete_volume, self.volumes_client,
lkuchlanc6e88a62016-12-08 17:12:31 +020045 restored_volume['volume_id'])
46 self.assertEqual(backup_id, restored_volume['backup_id'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020047 waiters.wait_for_volume_resource_status(self.backups_client,
48 backup_id, 'available')
49 waiters.wait_for_volume_resource_status(self.volumes_client,
50 restored_volume['volume_id'],
51 'available')
lkuchlanc6e88a62016-12-08 17:12:31 +020052 return restored_volume
53
Jon Bernardcf769af2017-04-06 15:38:01 -040054 @testtools.skipIf(CONF.volume.storage_protocol == 'ceph',
55 'ceph does not support arbitrary container names')
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -080056 @decorators.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
lkuchlanf8a66682016-06-16 14:49:19 +030057 def test_volume_backup_create_get_detailed_list_restore_delete(self):
zhufl067bcd02020-08-14 16:56:34 +080058 """Test create/get/list/restore/delete volume backup
59
60 1. Create volume1 with metadata
61 2. Create backup1 from volume1
62 3. Show backup1
63 4. List backups with detail
64 5. Restore backup1
65 6. Verify backup1 has been restored successfully with the metadata
66 of volume1
67 """
lkuchlana7fd37a2017-02-12 16:25:54 +020068 # Create a volume with metadata
69 metadata = {"vol-meta1": "value1",
70 "vol-meta2": "value2",
71 "vol-meta3": "value3"}
72 volume = self.create_volume(metadata=metadata)
zhuflcae2a752017-11-24 12:43:43 +080073 self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
lkuchlana7fd37a2017-02-12 16:25:54 +020074
75 # Create a backup
zhuflc6ce5392016-08-17 14:34:37 +080076 backup_name = data_utils.rand_name(
77 self.__class__.__name__ + '-Backup')
lkuchlan9e52d6b2016-12-11 12:18:42 +020078 description = data_utils.rand_name("volume-backup-description")
lkuchlana2beb492016-08-17 12:42:44 +030079 backup = self.create_backup(volume_id=volume['id'],
lkuchlan9e52d6b2016-12-11 12:18:42 +020080 name=backup_name,
lkuchlanf62703b2017-04-04 14:50:55 +030081 description=description,
82 container='container')
lkuchlanf8a66682016-06-16 14:49:19 +030083 self.assertEqual(backup_name, backup['name'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020084 waiters.wait_for_volume_resource_status(self.volumes_client,
85 volume['id'], 'available')
lkuchlanf8a66682016-06-16 14:49:19 +030086
87 # Get a given backup
88 backup = self.backups_client.show_backup(backup['id'])['backup']
89 self.assertEqual(backup_name, backup['name'])
lkuchlan9e52d6b2016-12-11 12:18:42 +020090 self.assertEqual(description, backup['description'])
lkuchlanf62703b2017-04-04 14:50:55 +030091 self.assertEqual('container', backup['container'])
lkuchlanf8a66682016-06-16 14:49:19 +030092
93 # Get all backups with detail
zhufl93a047f2018-11-08 14:35:49 +080094 backups = self.backups_client.list_backups(detail=True)['backups']
lkuchlanf8a66682016-06-16 14:49:19 +030095 self.assertIn((backup['name'], backup['id']),
96 [(m['name'], m['id']) for m in backups])
97
lkuchlana7fd37a2017-02-12 16:25:54 +020098 restored_volume = self.restore_backup(backup['id'])
99
100 restored_volume_metadata = self.volumes_client.show_volume(
101 restored_volume['volume_id'])['volume']['metadata']
102
zhufl067bcd02020-08-14 16:56:34 +0800103 # Verify the backup has been restored successfully
lkuchlana7fd37a2017-02-12 16:25:54 +0200104 # with the metadata of the source volume.
105 self.assertThat(restored_volume_metadata.items(),
106 matchers.ContainsAll(metadata.items()))
lkuchlanf8a66682016-06-16 14:49:19 +0300107
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -0800108 @decorators.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
Andrea Frittolicd368412017-08-14 21:37:56 +0100109 @utils.services('compute')
lkuchlan9dea88e2016-06-07 17:12:01 +0300110 def test_backup_create_attached_volume(self):
111 """Test backup create using force flag.
112
113 Cinder allows to create a volume backup, whether the volume status
114 is "available" or "in-use".
115 """
116 # Create a server
lisalibf543c32016-08-24 17:11:20 +0800117 volume = self.create_volume()
zhuflcae2a752017-11-24 12:43:43 +0800118 self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
lkuchland4ecd0e2017-06-11 12:01:27 +0300119 server = self.create_server()
lkuchlan9dea88e2016-06-07 17:12:01 +0300120 # Attach volume to instance
lkuchland818ef32017-01-11 12:22:22 +0200121 self.attach_volume(server['id'], volume['id'])
lkuchlan9dea88e2016-06-07 17:12:01 +0300122 # Create backup using force flag
zhuflc6ce5392016-08-17 14:34:37 +0800123 backup_name = data_utils.rand_name(
124 self.__class__.__name__ + '-Backup')
lkuchlana2beb492016-08-17 12:42:44 +0300125 backup = self.create_backup(volume_id=volume['id'],
126 name=backup_name, force=True)
jeremy.zhangd1be5012018-06-06 17:25:39 +0800127 waiters.wait_for_volume_resource_status(self.volumes_client,
128 volume['id'], 'in-use')
lkuchlan9dea88e2016-06-07 17:12:01 +0300129 self.assertEqual(backup_name, backup['name'])
130
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -0800131 @decorators.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
Andrea Frittolicd368412017-08-14 21:37:56 +0100132 @utils.services('image')
lkuchlanc6e88a62016-12-08 17:12:31 +0200133 def test_bootable_volume_backup_and_restore(self):
zhufl067bcd02020-08-14 16:56:34 +0800134 """Test backuping and restoring a bootable volume
135
136 1. Create volume1 from image
137 2. Create backup1 from volume1
138 3. Restore backup1
139 4. Verify the restored backup volume is bootable
140 """
lkuchlanc6e88a62016-12-08 17:12:31 +0200141 # Create volume from image
142 img_uuid = CONF.compute.image_ref
143 volume = self.create_volume(imageRef=img_uuid)
144
145 volume_details = self.volumes_client.show_volume(
146 volume['id'])['volume']
lkuchlana7aac722018-05-13 13:44:40 +0300147 self.assertTrue(volume_details['bootable'])
lkuchlanc6e88a62016-12-08 17:12:31 +0200148
149 # Create a backup
150 backup = self.create_backup(volume_id=volume['id'])
jeremy.zhangd1be5012018-06-06 17:25:39 +0800151 waiters.wait_for_volume_resource_status(self.volumes_client,
152 volume['id'], 'available')
lkuchlanc6e88a62016-12-08 17:12:31 +0200153
154 # Restore the backup
155 restored_volume_id = self.restore_backup(backup['id'])['volume_id']
156
157 # Verify the restored backup volume is bootable
158 restored_volume_info = self.volumes_client.show_volume(
159 restored_volume_id)['volume']
160
lkuchlana7aac722018-05-13 13:44:40 +0300161 self.assertTrue(restored_volume_info['bootable'])
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800162
163
164class VolumesBackupsV39Test(base.BaseVolumeTest):
zhufl067bcd02020-08-14 16:56:34 +0800165 """Test volumes backup with volume microversion greater than 3.8"""
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800166
Sophie Huangd458bf32021-10-12 17:08:41 +0000167 volume_min_microversion = '3.9'
168 volume_max_microversion = 'latest'
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800169
170 @classmethod
171 def skip_checks(cls):
172 super(VolumesBackupsV39Test, cls).skip_checks()
173 if not CONF.volume_feature_enabled.backup:
174 raise cls.skipException("Cinder backup feature disabled")
175
176 @decorators.idempotent_id('9b374cbc-be5f-4d37-8848-7efb8a873dcc')
177 def test_update_backup(self):
zhufl067bcd02020-08-14 16:56:34 +0800178 """Test updating backup's name and description"""
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800179 # Create volume and backup
180 volume = self.create_volume()
181 backup = self.create_backup(volume_id=volume['id'])
jeremy.zhangd1be5012018-06-06 17:25:39 +0800182 waiters.wait_for_volume_resource_status(self.volumes_client,
183 volume['id'], 'available')
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800184
185 # Update backup and assert response body for update_backup method
186 update_kwargs = {
187 'name': data_utils.rand_name(self.__class__.__name__ + '-Backup'),
188 'description': data_utils.rand_name("volume-backup-description")
189 }
190 update_backup = self.backups_client.update_backup(
191 backup['id'], **update_kwargs)['backup']
192 self.assertEqual(backup['id'], update_backup['id'])
193 self.assertEqual(update_kwargs['name'], update_backup['name'])
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800194
195 # Assert response body for show_backup method
196 retrieved_backup = self.backups_client.show_backup(
197 backup['id'])['backup']
198 for key in update_kwargs:
199 self.assertEqual(update_kwargs[key], retrieved_backup[key])