Exemple #1
0
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()));
    }
Exemple #3
0
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;
}