Add restore_volume_id in backup
This patch is to add restore_volume_id in backup object. When restoring a volume from a backup, it saves the volume in backup object. Currently volume service and backup service are in same host. When backup service starts, it does cleanup tasks on both backups and volumes on current host. But with bp scalable-backup-service, backup service and volume services can run on different hosts. When doing cleanup tasks, we need to find out backing-up and restoring volumes related to the backups on current host. Backing-up volumes can be found with field backup.volume_id. Restoring volumes are found by new field backup.restore_volume_id. Change-Id: I757be7a5e47fc366c181400587b5a61fe3709a0b Partial-Implements: bp scalable-backup-service Co-Authored-By: Tom Barron <tpb@dyncloud.net>
This commit is contained in:
parent
54991b1086
commit
4c83280125
@ -365,8 +365,9 @@ class API(base.Base):
|
||||
# Setting the status here rather than setting at start and unrolling
|
||||
# for each error condition, it should be a very small window
|
||||
backup.status = fields.BackupStatus.RESTORING
|
||||
backup.restore_volume_id = volume.id
|
||||
backup.save()
|
||||
volume_host = volume_utils.extract_host(volume['host'], 'host')
|
||||
volume_host = volume_utils.extract_host(volume.host, 'host')
|
||||
self.db.volume_update(context, volume_id, {'status':
|
||||
'restoring-backup'})
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2015 Intel Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sqlalchemy import Column, MetaData, String, Table
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
backups = Table('backups', meta, autoload=True)
|
||||
restore_volume_id = Column('restore_volume_id', String(length=36))
|
||||
|
||||
backups.create_column(restore_volume_id)
|
@ -527,6 +527,7 @@ class Backup(BASE, CinderBase):
|
||||
num_dependent_backups = Column(Integer)
|
||||
snapshot_id = Column(String(36))
|
||||
data_timestamp = Column(DateTime)
|
||||
restore_volume_id = Column(String(36))
|
||||
|
||||
@validates('fail_reason')
|
||||
def validate_fail_reason(self, key, fail_reason):
|
||||
|
@ -38,7 +38,8 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
||||
# is_incremental and has_dependent_backups.
|
||||
# Version 1.2: Add new field snapshot_id and data_timestamp.
|
||||
# Version 1.3: Changed 'status' field to use BackupStatusField
|
||||
VERSION = '1.3'
|
||||
# Version 1.4: Add restore_volume_id
|
||||
VERSION = '1.4'
|
||||
|
||||
fields = {
|
||||
'id': fields.UUIDField(),
|
||||
@ -70,6 +71,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
||||
'num_dependent_backups': fields.IntegerField(),
|
||||
'snapshot_id': fields.StringField(nullable=True),
|
||||
'data_timestamp': fields.DateTimeField(nullable=True),
|
||||
'restore_volume_id': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
obj_extra_fields = ['name', 'is_incremental', 'has_dependent_backups']
|
||||
|
@ -97,6 +97,7 @@ OBJ_VERSIONS.add('1.0', {'Backup': '1.3', 'BackupImport': '1.3',
|
||||
'ConsistencyGroupList': '1.1', 'Service': '1.1',
|
||||
'Volume': '1.3', 'VolumeTypeList': '1.1'})
|
||||
OBJ_VERSIONS.add('1.1', {'Service': '1.2', 'ServiceList': '1.1'})
|
||||
OBJ_VERSIONS.add('1.2', {'Backup': '1.4', 'BackupImport': '1.4'})
|
||||
|
||||
|
||||
class CinderObjectRegistry(base.VersionedObjectRegistry):
|
||||
|
@ -37,6 +37,7 @@ fake_backup = {
|
||||
'temp_snapshot_id': None,
|
||||
'snapshot_id': None,
|
||||
'data_timestamp': None,
|
||||
'restore_volume_id': None,
|
||||
}
|
||||
|
||||
|
||||
@ -94,6 +95,11 @@ class TestBackup(test_objects.BaseObjectsTestCase):
|
||||
snapshot_id='2')
|
||||
self.assertEqual('2', backup.snapshot_id)
|
||||
|
||||
def test_obj_field_restore_volume_id(self):
|
||||
backup = objects.Backup(context=self.context,
|
||||
restore_volume_id='2')
|
||||
self.assertEqual('2', backup.restore_volume_id)
|
||||
|
||||
def test_import_record(self):
|
||||
utils.replace_obj_loader(self, objects.Backup)
|
||||
backup = objects.Backup(context=self.context, id=1, parent_id=None,
|
||||
|
@ -21,8 +21,8 @@ from cinder import test
|
||||
# NOTE: The hashes in this list should only be changed if they come with a
|
||||
# corresponding version bump in the affected objects.
|
||||
object_data = {
|
||||
'Backup': '1.3-2e63492190bbbc85c0e5bea328cd38f7',
|
||||
'BackupImport': '1.3-2e63492190bbbc85c0e5bea328cd38f7',
|
||||
'Backup': '1.4-1002c50b6e31938583c95c4c4889286c',
|
||||
'BackupImport': '1.4-1002c50b6e31938583c95c4c4889286c',
|
||||
'BackupList': '1.0-24591dabe26d920ce0756fe64cd5f3aa',
|
||||
'CGSnapshot': '1.0-190da2a2aa9457edc771d888f7d225c4',
|
||||
'CGSnapshotList': '1.0-e8c3f4078cd0ee23487b34d173eec776',
|
||||
|
@ -1283,3 +1283,15 @@ class BackupAPITestCase(BaseBackupTest):
|
||||
description="test backup description",
|
||||
volume_id=volume_id,
|
||||
container='volumebackups')
|
||||
|
||||
@mock.patch('cinder.backup.rpcapi.BackupAPI.restore_backup')
|
||||
def test_restore_volume(self,
|
||||
mock_rpcapi_restore):
|
||||
ctxt = context.RequestContext('fake', 'fake')
|
||||
volume_id = self._create_volume_db_entry(status='available',
|
||||
size=1)
|
||||
backup = self._create_backup_db_entry(size=1,
|
||||
status='available')
|
||||
self.api.restore(ctxt, backup.id, volume_id)
|
||||
backup = objects.Backup.get_by_id(ctxt, backup.id)
|
||||
self.assertEqual(volume_id, backup.restore_volume_id)
|
||||
|
@ -1903,7 +1903,8 @@ class DBAPIBackupTestCase(BaseTest):
|
||||
'temp_volume_id': 'temp_volume_id',
|
||||
'temp_snapshot_id': 'temp_snapshot_id',
|
||||
'num_dependent_backups': 0,
|
||||
'snapshot_id': 'snapshot_id', }
|
||||
'snapshot_id': 'snapshot_id',
|
||||
'restore_volume_id': 'restore_volume_id'}
|
||||
if one:
|
||||
return base_values
|
||||
|
||||
|
@ -725,6 +725,11 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
|
||||
self.assertIsInstance(volume_type_projects.c.id.type,
|
||||
self.INTEGER_TYPE)
|
||||
|
||||
def _check_064(self, engine, data):
|
||||
backups = db_utils.get_table(engine, 'backups')
|
||||
self.assertIsInstance(backups.c.restore_volume_id.type,
|
||||
self.VARCHAR_TYPE)
|
||||
|
||||
def test_walk_versions(self):
|
||||
self.walk_versions(False, False)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user