def restore(self, backup, volume_id, volume_file): """Restore the given volume backup from swift.""" backup_id = backup['id'] container = backup['container'] object_prefix = backup['service_metadata'] LOG.debug( 'starting restore of backup %(object_prefix)s from swift' ' container: %(container)s, to volume %(volume_id)s, ' 'backup: %(backup_id)s' % { 'object_prefix': object_prefix, 'container': container, 'volume_id': volume_id, 'backup_id': backup_id, }) try: metadata = self._read_metadata(backup) except socket.error as err: raise exception.SwiftConnectionFailed(reason=err) metadata_version = metadata['version'] LOG.debug('Restoring swift backup version %s', metadata_version) try: restore_func = getattr( self, self.DRIVER_VERSION_MAPPING.get(metadata_version)) except TypeError: err = (_('No support to restore swift backup version %s') % metadata_version) raise exception.InvalidBackup(reason=err) restore_func(backup, volume_id, metadata, volume_file) volume_meta = metadata.get('volume_meta', None) try: if volume_meta: self.put_metadata(volume_id, volume_meta) else: LOG.debug("No volume metadata in this backup") except exception.BackupMetadataUnsupportedVersion: msg = _("Metadata restore failed due to incompatible version") LOG.error(msg) raise exception.BackupOperationError(msg) LOG.debug('restore %(backup_id)s to %(volume_id)s finished.' % { 'backup_id': backup_id, 'volume_id': volume_id })
def _restore_metadata(self, backup, volume_id): """Restore volume metadata from backup. If this backup has associated metadata, save it to the restore target otherwise do nothing. """ try: with rbd_driver.RADOSClient(self) as client: meta_bak = VolumeMetadataBackup(client, backup['id']) meta = meta_bak.get() if meta is not None: self.put_metadata(volume_id, meta) else: LOG.debug("Volume %s has no backed up metadata.", backup['volume_id']) except exception.BackupMetadataUnsupportedVersion: msg = _("Metadata restore failed due to incompatible version") LOG.error(msg) raise exception.BackupOperationError(msg)
def _backup_metadata(self, backup): """Backup volume metadata. NOTE(dosaboy): the metadata we are backing up is obtained from a versioned api so we should not alter it in any way here. We must also be sure that the service that will perform the restore is compatible with version used. """ json_meta = self.get_metadata(backup['volume_id']) if not json_meta: LOG.debug("No volume metadata to backup") return LOG.debug("Backing up volume metadata") try: with rbd_driver.RADOSClient(self) as client: vol_meta_backup = VolumeMetadataBackup(client, backup['id']) vol_meta_backup.set(json_meta) except exception.VolumeMetadataBackupExists as e: msg = _("Failed to backup volume metadata - %s") % (str(e)) raise exception.BackupOperationError(msg)
def restore(self, backup, target_volume_id, volume_file): LOG.info( 'Starting restore...... restore from src_volume:%(src)s to dst_volume:%(dst)s' % { 'src': backup['volume_id'], 'dst': str("volume-" + target_volume_id) }) backup_id = backup['id'] url = 'http://' + self._server_ip + '/v2/admin/backups/' + backup_id + '/restore' data = {"restore": {"volume_id": target_volume_id}} jdata = json.dumps(data) req = urllib2.Request(url, jdata) req.add_header('Content-type', 'application/json') try: response = urllib2.urlopen(req) LOG.debug(response.read()) except urllib2.HTTPError, e: LOG.debug(e.code) msg = "redirect restore cmd failed!" raise exception.BackupOperationError(msg)
def mock_backup_metadata_side_effect(backup): raise exception.BackupOperationError(_('mock'))
def fake_delete(self, backup): raise exception.BackupOperationError()
def restore(self, backup, volume_id, volume_file): """Restore the given volume backup from backup repository. Raises BackupRestoreCancel on any backup status change. """ backup_id = backup['id'] container = backup['container'] object_prefix = backup['service_metadata'] LOG.debug( 'starting restore of backup %(object_prefix)s ' 'container: %(container)s, to volume %(volume_id)s, ' 'backup: %(backup_id)s.', { 'object_prefix': object_prefix, 'container': container, 'volume_id': volume_id, 'backup_id': backup_id, }) metadata = self._read_metadata(backup) metadata_version = metadata['version'] LOG.debug('Restoring backup version %s', metadata_version) try: restore_func = getattr( self, self.DRIVER_VERSION_MAPPING.get(metadata_version)) except TypeError: err = (_('No support to restore backup version %s') % metadata_version) raise exception.InvalidBackup(reason=err) # Build a list of backups based on parent_id. A full backup # will be the last one in the list. backup_list = [] backup_list.append(backup) current_backup = backup while current_backup.parent_id: prev_backup = objects.Backup.get_by_id(self.context, current_backup.parent_id) backup_list.append(prev_backup) current_backup = prev_backup # Do a full restore first, then layer the incremental backups # on top of it in order. index = len(backup_list) - 1 while index >= 0: backup1 = backup_list[index] index = index - 1 metadata = self._read_metadata(backup1) restore_func(backup1, volume_id, metadata, volume_file, backup) volume_meta = metadata.get('volume_meta', None) try: if volume_meta: self.put_metadata(volume_id, volume_meta) else: LOG.debug("No volume metadata in this backup.") except exception.BackupMetadataUnsupportedVersion: msg = _("Metadata restore failed due to incompatible version.") LOG.error(msg) raise exception.BackupOperationError(msg) LOG.debug('restore %(backup_id)s to %(volume_id)s finished.', { 'backup_id': backup_id, 'volume_id': volume_id })
class SheepdogBackupDriver(BackupDriver): def __init__(self, context, db_driver=None): super(SheepdogBackupDriver, self).__init__(db_driver) self.context = context self._server_ip = self._utf8(CONF.cinder_ip) @staticmethod def _utf8(s): """Ensure string s is utf8 (i.e. not unicode).""" if isinstance(s, str): return s return s.encode('utf8') def backup(self, backup, volume_file): LOG.info('Starting backup...... Creating a new backup for volume:%s.' % backup['volume_id']) backup_id = backup['id'] url = 'http://' + self._server_ip + '/v2/admin/backups' data = { "backup": { "container": backup['container'], "description": backup['display_description'], "name": backup['display_name'], "volume_id": backup['volume_id'], "backupid": backup_id } } jdata = json.dumps(data) req = urllib2.Request(url, jdata) req.add_header('Content-type', 'application/json') try: response = urllib2.urlopen(req) LOG.debug(response.read()) except urllib2.HTTPError, e: LOG.debug(e.code) msg = "redirect backup cmd failed!" raise exception.BackupOperationError(msg) while True: url = 'http://' + self._server_ip + '/v2/admin/backups/' + backup_id try: response = urllib2.urlopen(url) ret = response.read() LOG.debug("RET: %r" % ret) data = json.loads(ret) except urllib2.HTTPError, e: LOG.debug(e.code) msg = "confirm backup cmd failed!" raise exception.BackupOperationError(msg) if data['backup']['status'] == 'available': size = data['backup']['object_count'] LOG.debug("size %s MB." % size) LOG.info('backup finished.') break time.sleep(3)
LOG.debug(e.code) msg = "redirect restore cmd failed!" raise exception.BackupOperationError(msg) while True: url = 'http://' + self._server_ip + '/v2/admin/backups/' + backup_id try: response = urllib2.urlopen(url) ret = response.read() LOG.debug("RET: %r" % ret) data = json.loads(ret) except urllib2.HTTPError, e: LOG.debug(e.code) msg = "confirm restore cmd failed!" raise exception.BackupOperationError(msg) if data['backup']['status'] == 'available': LOG.info('restore finished.') break time.sleep(3) def delete(self, backup): LOG.info('Starting delete...... backupid:%s' % backup['id']) backup_id = backup['id'] url = 'http://' + self._server_ip + '/v2/admin/backups/' + backup_id req = urllib2.Request(url)