blob: c179c352c36c442e842b418c9876c8629c55631c [file] [log] [blame]
Giulio Fidente74b08ad2014-01-18 04:02:51 +01001# Copyright 2014 OpenStack Foundation
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
Sirushti Murugesan12dc9732016-07-13 22:49:17 +053016from oslo_serialization import base64
Gorka Eguileor9de20c12015-08-13 11:16:43 +020017from oslo_serialization import jsonutils as json
18
Masayuki Igawa1edf94f2014-03-04 18:34:16 +090019from tempest.api.volume import base
Yaroslav Lobankoved3a35b2016-03-24 22:41:30 -050020from tempest.common import waiters
Giulio Fidente74b08ad2014-01-18 04:02:51 +010021from 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
Giulio Fidente74b08ad2014-01-18 04:02:51 +010024
25CONF = config.CONF
Giulio Fidente74b08ad2014-01-18 04:02:51 +010026
27
Ken'ichi Ohmichie8afb8c2017-03-27 11:25:37 -070028class VolumesBackupsAdminTest(base.BaseVolumeAdminTest):
Giulio Fidente74b08ad2014-01-18 04:02:51 +010029
30 @classmethod
Rohan Kanade05749152015-01-30 17:15:18 +053031 def skip_checks(cls):
Ken'ichi Ohmichie8afb8c2017-03-27 11:25:37 -070032 super(VolumesBackupsAdminTest, cls).skip_checks()
Giulio Fidente74b08ad2014-01-18 04:02:51 +010033 if not CONF.volume_feature_enabled.backup:
34 raise cls.skipException("Cinder backup feature disabled")
35
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000036 def _delete_backup(self, backup_id):
bkopilov62d21752016-06-08 10:16:11 +030037 self.admin_backups_client.delete_backup(backup_id)
Ken'ichi Ohmichi153b3d92016-08-03 14:35:46 -070038 self.admin_backups_client.wait_for_resource_deletion(backup_id)
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000039
Gorka Eguileor9de20c12015-08-13 11:16:43 +020040 def _decode_url(self, backup_url):
Sirushti Murugesan12dc9732016-07-13 22:49:17 +053041 return json.loads(base64.decode_as_text(backup_url))
Gorka Eguileor9de20c12015-08-13 11:16:43 +020042
43 def _encode_backup(self, backup):
44 retval = json.dumps(backup)
Sirushti Murugesan12dc9732016-07-13 22:49:17 +053045 return base64.encode_as_text(retval)
Gorka Eguileor9de20c12015-08-13 11:16:43 +020046
47 def _modify_backup_url(self, backup_url, changes):
48 backup = self._decode_url(backup_url)
49 backup.update(changes)
50 return self._encode_backup(backup)
51
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -080052 @decorators.idempotent_id('a99c54a1-dd80-4724-8a13-13bf58d4068d')
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000053 def test_volume_backup_export_import(self):
Gorka Eguileor9de20c12015-08-13 11:16:43 +020054 """Test backup export import functionality.
55
56 Cinder allows exporting DB backup information through its API so it can
57 be imported back in case of a DB loss.
58 """
lkuchlana2beb492016-08-17 12:42:44 +030059 volume = self.create_volume()
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000060 # Create backup
zhuflc6ce5392016-08-17 14:34:37 +080061 backup_name = data_utils.rand_name(self.__class__.__name__ + '-Backup')
jeremy.zhang112b8442018-05-30 22:20:50 +080062 backup = self.create_backup(volume_id=volume['id'], name=backup_name)
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000063 self.assertEqual(backup_name, backup['name'])
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000064
65 # Export Backup
bkopilov62d21752016-06-08 10:16:11 +030066 export_backup = (self.admin_backups_client.export_backup(backup['id'])
John Warren6cadeee2015-08-13 17:00:56 +000067 ['backup-record'])
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000068 self.assertIn('backup_service', export_backup)
69 self.assertIn('backup_url', export_backup)
70 self.assertTrue(export_backup['backup_service'].startswith(
71 'cinder.backup.drivers'))
72 self.assertIsNotNone(export_backup['backup_url'])
73
Gorka Eguileor9de20c12015-08-13 11:16:43 +020074 # NOTE(geguileo): Backups are imported with the same backup id
75 # (important for incremental backups among other things), so we cannot
76 # import the exported backup information as it is, because that Backup
77 # ID already exists. So we'll fake the data by changing the backup id
78 # in the exported backup DB info we have retrieved before importing it
79 # back.
80 new_id = data_utils.rand_uuid()
81 new_url = self._modify_backup_url(
82 export_backup['backup_url'], {'id': new_id})
83
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000084 # Import Backup
bkopilov62d21752016-06-08 10:16:11 +030085 import_backup = self.admin_backups_client.import_backup(
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000086 backup_service=export_backup['backup_service'],
Gorka Eguileor9de20c12015-08-13 11:16:43 +020087 backup_url=new_url)['backup']
88
89 # NOTE(geguileo): We delete both backups, but only one of those
90 # deletions will delete data from the backup back-end because they
91 # were both pointing to the same backend data.
92 self.addCleanup(self._delete_backup, new_id)
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000093 self.assertIn("id", import_backup)
Gorka Eguileor9de20c12015-08-13 11:16:43 +020094 self.assertEqual(new_id, import_backup['id'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020095 waiters.wait_for_volume_resource_status(self.admin_backups_client,
96 import_backup['id'],
97 'available')
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +000098
99 # Verify Import Backup
zhuflf0e8beb2017-08-22 10:56:26 +0800100 backups = self.admin_backups_client.list_backups()['backups']
Gorka Eguileor9de20c12015-08-13 11:16:43 +0200101 self.assertIn(new_id, [b['id'] for b in backups])
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +0000102
103 # Restore backup
jeremy.zhang112b8442018-05-30 22:20:50 +0800104 restore = self.backups_client.restore_backup(backup['id'])['restore']
105 self.addCleanup(self.volumes_client.delete_volume,
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +0000106 restore['volume_id'])
Gorka Eguileor9de20c12015-08-13 11:16:43 +0200107 self.assertEqual(backup['id'], restore['backup_id'])
jeremy.zhang04e1d672018-06-07 14:56:36 +0800108
109 # When restore operation is performed then, backup['id']
110 # goes to 'restoring' state so we need to wait for
111 # backup['id'] to become 'available'.
112 waiters.wait_for_volume_resource_status(
113 self.backups_client, backup['id'], 'available')
114 waiters.wait_for_volume_resource_status(
115 self.volumes_client, restore['volume_id'], 'available')
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +0000116
117 # Verify if restored volume is there in volume list
jeremy.zhang112b8442018-05-30 22:20:50 +0800118 volumes = self.volumes_client.list_volumes()['volumes']
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +0000119 self.assertIn(restore['volume_id'], [v['id'] for v in volumes])
ravikumar-venkatesan18c1d0e2015-03-18 11:28:37 +0000120
Ken'ichi Ohmichi6b279c72017-01-27 18:26:59 -0800121 @decorators.idempotent_id('47a35425-a891-4e13-961c-c45deea21e94')
Ghanshyam Mannb0d15bf2017-05-02 04:55:47 +0000122 def test_volume_backup_reset_status(self):
lkuchlana2beb492016-08-17 12:42:44 +0300123 # Create a volume
124 volume = self.create_volume()
bkopilov19fc5fd2016-07-06 12:02:18 +0300125 # Create a backup
zhuflc6ce5392016-08-17 14:34:37 +0800126 backup_name = data_utils.rand_name(
127 self.__class__.__name__ + '-Backup')
jeremy.zhang112b8442018-05-30 22:20:50 +0800128 backup = self.create_backup(volume_id=volume['id'], name=backup_name)
bkopilov19fc5fd2016-07-06 12:02:18 +0300129 self.assertEqual(backup_name, backup['name'])
bkopilov19fc5fd2016-07-06 12:02:18 +0300130 # Reset backup status to error
131 self.admin_backups_client.reset_backup_status(backup_id=backup['id'],
132 status="error")
jeremy.zhang112b8442018-05-30 22:20:50 +0800133 waiters.wait_for_volume_resource_status(self.backups_client,
lkuchlan52d7b0d2016-11-07 20:53:19 +0200134 backup['id'], 'error')