void Backup::get_target_volume_info() { LOG_INFO(__FUNCTION__); try { target_volume_config.reset(new VolumeConfig()); const fs::path p = file_pool->newFile("target_volume_config"); BackendInterfacePtr bip = VolManager::get()->createBackendInterface(backend::Namespace(target_namespace)); bip->read(p, VolumeConfig::config_backend_name, InsistOnLatestVersion::T); fs::ifstream ifs(p); VolumeConfig::iarchive_type ia(ifs); ia & *target_volume_config; ifs.close(); } catch(std::exception& e) { LOG_FATAL("Could not get source volume info from it's backend, " << e.what()); throw; } catch(...) { LOG_FATAL("Could not get source volume info from it's backend, unknown exception" ); throw; } }
void truncate_sco_in_backend(SCO sco, uint64_t size) { BackendInterfacePtr bi = vol_->getBackendInterface()->clone(); ASSERT_TRUE(bi != 0); fs::path tmp_file; ASSERT_NO_THROW(tmp_file = yt::FileUtils::create_temp_file(yt::FileUtils::temp_path(), sco.str())); ALWAYS_CLEANUP_FILE(tmp_file); ASSERT_NO_THROW(bi->read(tmp_file, sco.str(), InsistOnLatestVersion::T)); ASSERT_TRUE(fs::exists(tmp_file)); FileUtils::truncate(tmp_file, size); ASSERT_NO_THROW(bi->write(tmp_file, sco.str(), OverwriteObject::T)); EXPECT_EQ(size, bi->getSize(sco.str())); }
bool Backup::preexisting_volume_checks() { LOG_INFO(__FUNCTION__); VERIFY(source_snapshot_persistor); VERIFY(target_volume_); api::getManagementMutex().assertLocked(); if(start_snapshot_) { const SnapshotName& start_snapshot_name = *start_snapshot_; const SnapshotNum start_snapshot_num = source_snapshot_persistor->getSnapshotNum(*start_snapshot_); const UUID start_snapshot_uuid = source_snapshot_persistor->getUUID(start_snapshot_num); LOG_INFO("Backup target volume existed, figuring out if we need to do work"); // We are going to apply an incremental with snapshot matching //const SnapshotNum start_snapshot_num = source_snapshot_persistor.getSnapshotNum(*start_snapshot); if(not api::checkSnapshotUUID(target_volume_.get(), start_snapshot_name, start_snapshot_uuid)) { LOG_FATAL("Snapshot with name " << start_snapshot_name << " has non matching guids, exiting"); throw BackupException("Non matching guids"); } else if(api::snapshotExists(target_volume_.get(), end_snapshot_name)) { const UUID end_snapshot_uuid = source_snapshot_persistor->getUUID(end_snapshot_number); if(api::checkSnapshotUUID(target_volume_.get(), end_snapshot_name, end_snapshot_uuid)) { LOG_INFO("Start and end are already on target and guids match, lovely!"); LOG_INFO("Exiting early"); { status_.finish(); } return false; } else { LOG_INFO("Start snapshot was on target but end snapshot had different guid"); boost::this_thread::interruption_point(); api::restoreSnapshot(target_volume_.get(), start_snapshot_name); } } else { LOG_INFO("Start snapshot was on target but end snapshot not"); boost::this_thread::interruption_point(); api::restoreSnapshot(target_volume_.get(), start_snapshot_name); } } else { LOG_INFO("Backup volume existed but no start snapshot was given... trying to find the best place to backup from"); LOG_INFO("Getting the list of snapshots from the target"); std::list<SnapshotName> snapshots_list; api::showSnapshots(target_volume_.get(), snapshots_list); if(snapshots_list.empty()) { LOG_WARN("No snapshots in backed up volume, something went wrong??"); LOG_WARN("Checking for a failed first backup because the snapshots list is empty"); get_target_volume_info(); if(source_volume_config->getNS().str() != target_volume_config->id_) { LOG_FATAL("No snapshot on the volume and volume names don't match: " << source_volume_config->getNS() << " vs. " << std::string(target_volume_config->id_)); throw BackupException("Volume on backup had no snapshots and wrong volume name"); } if(target_volume_config->wan_backup_volume_role_ != VolumeConfig::WanBackupVolumeRole::WanBackupBase) { LOG_FATAL("Target volume exists, has not snapshot and names match but has the wrong role"); throw BackupException("Volume on backup had no snapshots and wrong role"); } LOG_WARN("Seems to have been a botched backup, cleaning up"); BackendInterfacePtr bip = VolManager::get()->createBackendInterface(target_namespace); std::list<std::string> objects; bip->listObjects(objects); BackendNamesFilter is_vd_object; for (const auto& o : objects) { if (is_vd_object(o)) { LOG_INFO("Removing " << o); bip->remove(o); } } throw RetryCreateVolume(); } SnapshotName snapshot_to_be_restored; LOG_INFO("Looping of target snapshotshots to find latest that can be matched"); for(std::list<SnapshotName>::const_reverse_iterator i = snapshots_list.rbegin(); i != snapshots_list.rend(); ++i) { const SnapshotName& snap_name = *i; if(source_snapshot_persistor->snapshotExists(snap_name)) { SnapshotNum num = source_snapshot_persistor->getSnapshotNum(snap_name); UUID snap_uuid = source_snapshot_persistor->getUUID(num); if(api::checkSnapshotUUID(target_volume_.get(), snap_name, snap_uuid)) { snapshot_to_be_restored = snap_name; break; } else { LOG_FATAL("Snapshot with the same name but different guid found, " << snap_name); throw BackupException("Guid confusion"); } } } if(snapshot_to_be_restored.empty()) { LOG_FATAL("Could not find a matching snapshot "); throw BackupException("Could not find a matching snapshot"); } else if(snapshot_to_be_restored == end_snapshot_name) { LOG_INFO("snapshot to be restored == end snapshot, exiting early"); { status_.finish(); } return false; } // Y42 we might be a lot smarter here LOG_INFO("Connecting snapshot found as " << snapshot_to_be_restored); LOG_INFO("Doing a restore to that snapshot on the target volume"); boost::this_thread::interruption_point(); api::restoreSnapshot(target_volume_.get(), snapshot_to_be_restored); start_snapshot_ = snapshot_to_be_restored; } status_.start_snapshot(start_snapshot_.get_value_or(SnapshotName())); return true; }