blob: 6ce5d3ee889ca03bebdba8a0a3bbf9115b4967d8 [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):
lkuchlan9dea88e2016-06-07 17:12:01 +030030
31 @classmethod
32 def skip_checks(cls):
Ken'ichi Ohmichie8afb8c2017-03-27 11:25:37 -070033 super(VolumesBackupsTest, cls).skip_checks()
lkuchlan9dea88e2016-06-07 17:12:01 +030034 if not CONF.volume_feature_enabled.backup:
35 raise cls.skipException("Cinder backup feature disabled")
36
lkuchlanc6e88a62016-12-08 17:12:31 +020037 def restore_backup(self, backup_id):
38 # Restore a backup
39 restored_volume = self.backups_client.restore_backup(
40 backup_id)['restore']
41
42 # Delete backup
zhuflcae2a752017-11-24 12:43:43 +080043 self.addCleanup(self.delete_volume, self.volumes_client,
lkuchlanc6e88a62016-12-08 17:12:31 +020044 restored_volume['volume_id'])
45 self.assertEqual(backup_id, restored_volume['backup_id'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020046 waiters.wait_for_volume_resource_status(self.backups_client,
47 backup_id, 'available')
48 waiters.wait_for_volume_resource_status(self.volumes_client,
49 restored_volume['volume_id'],
50 'available')
lkuchlanc6e88a62016-12-08 17:12:31 +020051 return restored_volume
52
Ghanshyam Mann762e98c2019-04-11 07:15:40 +090053 @decorators.skip_because(bug="1483434")
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):
lkuchlana7fd37a2017-02-12 16:25:54 +020058 # Create a volume with metadata
59 metadata = {"vol-meta1": "value1",
60 "vol-meta2": "value2",
61 "vol-meta3": "value3"}
62 volume = self.create_volume(metadata=metadata)
zhuflcae2a752017-11-24 12:43:43 +080063 self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
lkuchlana7fd37a2017-02-12 16:25:54 +020064
65 # Create a backup
zhuflc6ce5392016-08-17 14:34:37 +080066 backup_name = data_utils.rand_name(
67 self.__class__.__name__ + '-Backup')
lkuchlan9e52d6b2016-12-11 12:18:42 +020068 description = data_utils.rand_name("volume-backup-description")
lkuchlana2beb492016-08-17 12:42:44 +030069 backup = self.create_backup(volume_id=volume['id'],
lkuchlan9e52d6b2016-12-11 12:18:42 +020070 name=backup_name,
lkuchlanf62703b2017-04-04 14:50:55 +030071 description=description,
72 container='container')
lkuchlanf8a66682016-06-16 14:49:19 +030073 self.assertEqual(backup_name, backup['name'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020074 waiters.wait_for_volume_resource_status(self.volumes_client,
75 volume['id'], 'available')
lkuchlanf8a66682016-06-16 14:49:19 +030076
77 # Get a given backup
78 backup = self.backups_client.show_backup(backup['id'])['backup']
79 self.assertEqual(backup_name, backup['name'])
lkuchlan9e52d6b2016-12-11 12:18:42 +020080 self.assertEqual(description, backup['description'])
lkuchlanf62703b2017-04-04 14:50:55 +030081 self.assertEqual('container', backup['container'])
lkuchlanf8a66682016-06-16 14:49:19 +030082
83 # Get all backups with detail
84 backups = self.backups_client.list_backups(
85 detail=True)['backups']
zhuflf0e8beb2017-08-22 10:56:26 +080086 for backup_info in backups:
87 self.assertIn('created_at', backup_info)
88 self.assertIn('links', backup_info)
lkuchlanf8a66682016-06-16 14:49:19 +030089 self.assertIn((backup['name'], backup['id']),
90 [(m['name'], m['id']) for m in backups])
91
lkuchlana7fd37a2017-02-12 16:25:54 +020092 restored_volume = self.restore_backup(backup['id'])
93
94 restored_volume_metadata = self.volumes_client.show_volume(
95 restored_volume['volume_id'])['volume']['metadata']
96
97 # Verify the backups has been restored successfully
98 # with the metadata of the source volume.
99 self.assertThat(restored_volume_metadata.items(),
100 matchers.ContainsAll(metadata.items()))
lkuchlanf8a66682016-06-16 14:49:19 +0300101
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -0800102 @decorators.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
Andrea Frittolicd368412017-08-14 21:37:56 +0100103 @utils.services('compute')
lkuchlan9dea88e2016-06-07 17:12:01 +0300104 def test_backup_create_attached_volume(self):
105 """Test backup create using force flag.
106
107 Cinder allows to create a volume backup, whether the volume status
108 is "available" or "in-use".
109 """
110 # Create a server
lisalibf543c32016-08-24 17:11:20 +0800111 volume = self.create_volume()
zhuflcae2a752017-11-24 12:43:43 +0800112 self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
lkuchland4ecd0e2017-06-11 12:01:27 +0300113 server = self.create_server()
lkuchlan9dea88e2016-06-07 17:12:01 +0300114 # Attach volume to instance
lkuchland818ef32017-01-11 12:22:22 +0200115 self.attach_volume(server['id'], volume['id'])
lkuchlan9dea88e2016-06-07 17:12:01 +0300116 # Create backup using force flag
zhuflc6ce5392016-08-17 14:34:37 +0800117 backup_name = data_utils.rand_name(
118 self.__class__.__name__ + '-Backup')
lkuchlana2beb492016-08-17 12:42:44 +0300119 backup = self.create_backup(volume_id=volume['id'],
120 name=backup_name, force=True)
jeremy.zhangd1be5012018-06-06 17:25:39 +0800121 waiters.wait_for_volume_resource_status(self.volumes_client,
122 volume['id'], 'in-use')
lkuchlan9dea88e2016-06-07 17:12:01 +0300123 self.assertEqual(backup_name, backup['name'])
124
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -0800125 @decorators.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
Andrea Frittolicd368412017-08-14 21:37:56 +0100126 @utils.services('image')
lkuchlanc6e88a62016-12-08 17:12:31 +0200127 def test_bootable_volume_backup_and_restore(self):
128 # Create volume from image
129 img_uuid = CONF.compute.image_ref
130 volume = self.create_volume(imageRef=img_uuid)
131
132 volume_details = self.volumes_client.show_volume(
133 volume['id'])['volume']
lkuchlana7aac722018-05-13 13:44:40 +0300134 self.assertTrue(volume_details['bootable'])
lkuchlanc6e88a62016-12-08 17:12:31 +0200135
136 # Create a backup
137 backup = self.create_backup(volume_id=volume['id'])
jeremy.zhangd1be5012018-06-06 17:25:39 +0800138 waiters.wait_for_volume_resource_status(self.volumes_client,
139 volume['id'], 'available')
lkuchlanc6e88a62016-12-08 17:12:31 +0200140
141 # Restore the backup
142 restored_volume_id = self.restore_backup(backup['id'])['volume_id']
143
144 # Verify the restored backup volume is bootable
145 restored_volume_info = self.volumes_client.show_volume(
146 restored_volume_id)['volume']
147
lkuchlana7aac722018-05-13 13:44:40 +0300148 self.assertTrue(restored_volume_info['bootable'])
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800149
150
151class VolumesBackupsV39Test(base.BaseVolumeTest):
152
153 _api_version = 3
154 min_microversion = '3.9'
155 max_microversion = 'latest'
156
157 @classmethod
158 def skip_checks(cls):
159 super(VolumesBackupsV39Test, cls).skip_checks()
160 if not CONF.volume_feature_enabled.backup:
161 raise cls.skipException("Cinder backup feature disabled")
162
163 @decorators.idempotent_id('9b374cbc-be5f-4d37-8848-7efb8a873dcc')
164 def test_update_backup(self):
165 # Create volume and backup
166 volume = self.create_volume()
167 backup = self.create_backup(volume_id=volume['id'])
jeremy.zhangd1be5012018-06-06 17:25:39 +0800168 waiters.wait_for_volume_resource_status(self.volumes_client,
169 volume['id'], 'available')
jeremy.zhangf4ce4172017-07-05 12:27:35 +0800170
171 # Update backup and assert response body for update_backup method
172 update_kwargs = {
173 'name': data_utils.rand_name(self.__class__.__name__ + '-Backup'),
174 'description': data_utils.rand_name("volume-backup-description")
175 }
176 update_backup = self.backups_client.update_backup(
177 backup['id'], **update_kwargs)['backup']
178 self.assertEqual(backup['id'], update_backup['id'])
179 self.assertEqual(update_kwargs['name'], update_backup['name'])
180 self.assertIn('links', update_backup)
181
182 # Assert response body for show_backup method
183 retrieved_backup = self.backups_client.show_backup(
184 backup['id'])['backup']
185 for key in update_kwargs:
186 self.assertEqual(update_kwargs[key], retrieved_backup[key])