Merge "Add features for add backup id to volume metadata"

This commit is contained in:
Zuul 2020-04-07 10:27:52 +00:00 committed by Gerrit Code Review
commit 55de6d8866
3 changed files with 85 additions and 0 deletions

View File

@ -605,6 +605,16 @@ class BackupManager(manager.SchedulerDependentManager):
# attribute as well.
if volume_previous_status == fields.VolumeStatus.CREATING:
volume['launched_at'] = timeutils.utcnow()
old_src_backup_id = self.db.volume_metadata_get(
context, volume_id).get("src_backup_id", None)
if backup.volume_id != volume.id or (
old_src_backup_id and old_src_backup_id != backup.id):
self.db.volume_metadata_update(
context,
volume.id,
{'src_backup_id': backup.id},
False)
volume.save()
backup.status = fields.BackupStatus.AVAILABLE
backup.save()

View File

@ -1263,6 +1263,74 @@ class BackupTestCase(BaseBackupTest):
vol = objects.Volume.get_by_id(self.ctxt, vol_id)
self.assertEqual('available', vol['status'])
backup = db.backup_get(self.ctxt, backup.id)
self.assertNotEqual(backup.id, vol.metadata.get('src_backup_id'))
self.assertEqual(fields.BackupStatus.AVAILABLE, backup['status'])
@mock.patch('cinder.utils.brick_get_connector_properties')
@mock.patch('cinder.utils.temporary_chown')
@mock.patch('six.moves.builtins.open', wraps=open)
@mock.patch.object(os.path, 'isdir', return_value=False)
@ddt.data({'os_name': 'nt', 'exp_open_mode': 'rb+'},
{'os_name': 'posix', 'exp_open_mode': 'wb'})
@ddt.unpack
def test_restore_backup_new_volume(self,
mock_isdir,
mock_open,
mock_temporary_chown,
mock_get_conn,
os_name,
exp_open_mode):
"""Test normal backup restoration."""
vol_size = 1
vol_id = self._create_volume_db_entry(
status='restoring-backup', size=vol_size)
backup = self._create_backup_db_entry(
status=fields.BackupStatus.RESTORING, volume_id=vol_id)
vol2_id = self._create_volume_db_entry(
status='restoring-backup', size=vol_size)
backup2 = self._create_backup_db_entry(
status=fields.BackupStatus.RESTORING, volume_id=vol2_id)
vol2 = objects.Volume.get_by_id(self.ctxt, vol2_id)
properties = {}
mock_get_conn.return_value = properties
mock_secure_enabled = (
self.volume_mocks['secure_file_operations_enabled'])
mock_secure_enabled.return_value = False
new_vol_id = self._create_volume_db_entry(
status='restoring-backup', size=vol_size)
vol = objects.Volume.get_by_id(self.ctxt, new_vol_id)
attach_info = {'device': {'path': '/dev/null'}}
mock_attach_device = self.mock_object(self.backup_mgr,
'_attach_device')
self.mock_object(self.backup_mgr, '_detach_device')
mock_attach_device.return_value = attach_info
with mock.patch('os.name', os_name):
self.backup_mgr.restore_backup(self.ctxt, backup, new_vol_id)
backup.status = "restoring"
db.backup_update(self.ctxt, backup.id, {"status": "restoring"})
vol.status = 'available'
vol.obj_reset_changes()
with mock.patch('os.name', os_name):
self.backup_mgr.restore_backup(self.ctxt, backup, vol2_id)
vol2.status = 'restoring-backup'
db.volume_update(self.ctxt, vol2.id, {"status": "restoring-backup"})
vol2.obj_reset_changes()
with mock.patch('os.name', os_name):
self.backup_mgr.restore_backup(self.ctxt, backup2, vol2_id)
vol2.status = 'available'
vol2.obj_reset_changes()
vol = objects.Volume.get_by_id(self.ctxt, new_vol_id)
vol2 = objects.Volume.get_by_id(self.ctxt, vol2_id)
self.assertEqual('available', vol['status'])
backup = db.backup_get(self.ctxt, backup.id)
self.assertEqual(backup.id, vol.metadata["src_backup_id"])
self.assertEqual(backup2.id, vol2.metadata["src_backup_id"])
self.assertEqual(fields.BackupStatus.AVAILABLE, backup['status'])
@mock.patch('cinder.volume.volume_utils.notify_about_backup_usage')

View File

@ -0,0 +1,7 @@
---
features:
- |
Add the property ``src_backup_id`` to the volume's metadata,
to record from which backup the new volume was created.
When restoring from a chain of incremental backups, ``src_backup_id``
is set to the last incremental backup used for the restore.