TEST_P(SnapshotRestoreTest, TestFailOver)
{
    auto foc_ctx(start_one_foc());
    auto ns_ptr = make_random_namespace();
    SharedVolumePtr v = newVolume(VolumeId("volume1"),
                          ns_ptr->ns(),
                          VolumeSize((1 << 18) * 512),
                          SCOMultiplier(1));

    v->setFailOverCacheConfig(foc_ctx->config(GetParam().foc_mode()));

    VolumeConfig cfg = v->get_config();
    v->createSnapshot(SnapshotName("snap0"));

    for(int i = 0; i < 5; ++i)
    {
        writeToVolume(*v,
                      0,
                      4096,
                      "a");
    }


    waitForThisBackendWrite(*v);
    v->restoreSnapshot(SnapshotName("snap0"));

    for(int i = 0; i < 7; ++i)
    {
        writeToVolume(*v,
                      8,
                      4096,
                      "d");
    }

    flushFailOverCache(*v);
    destroyVolume(v,
                  DeleteLocalData::T,
                  RemoveVolumeCompletely::F);

    SharedVolumePtr v1 = 0;
    v1 = getVolume(VolumeId("volume1"));
    ASSERT_FALSE(v1);
    restartVolume(cfg);
    v1 = getVolume(VolumeId("volume1"));

    ASSERT_TRUE(v1 != nullptr);
    checkVolume(*v1,0,4096, "\0");
    checkVolume(*v1,8,4096, "d");
    checkCurrentBackendSize(*v1);
}
TEST_P(BigReadWriteTest, bigReadsOnFull)
{
    auto ns_ptr = make_random_namespace();
    SharedVolumePtr v = newVolume(VolumeId("volume1"),
                          ns_ptr->ns());

    SCOPED_BLOCK_BACKEND(*v);

    size_t csz = v->getClusterSize();
    size_t lba_size = v->getLBASize();

    const std::string pattern(csz,'a');
    size_t scoMul = v->getSCOMultiplier();
    for(size_t i = 0;i < 50*scoMul; ++i)
    {
        writeToVolume(*v, i* csz / lba_size, csz, pattern);
    }

    // Stop here to manually delete sco's to check error handling
    for(size_t i = 0; i < scoMul; ++i)
    {
        checkVolume(*v,0, csz*scoMul, pattern);
    }

}
TEST_P(SnapshotRestoreTest, snapshot_restoration_on_a_clone)
{
    const auto wrns_parent(make_random_namespace());
    const std::string parent_name(wrns_parent->ns().str());

    SharedVolumePtr parent = newVolume(VolumeId(parent_name),
                               be::Namespace(parent_name));

    const std::string pattern1("before-parent-snapshot");

    writeToVolume(*parent,
                  0,
                  parent->getClusterSize(),
                  pattern1);

    const SnapshotName parent_snap("parent-snapshot");
    parent->createSnapshot(parent_snap);

    waitForThisBackendWrite(*parent);

    const auto wrns_clone(make_random_namespace());
    const std::string clone_name(wrns_clone->ns().str());

    SharedVolumePtr clone = createClone(clone_name,
                                be::Namespace(clone_name),
                                be::Namespace(parent_name),
                                parent_snap);

    const std::string pattern2("before-clone-snapshot");

    writeToVolume(*clone,
                  0,
                  clone->getClusterSize(),
                  pattern2);

    const SnapshotName clone_snap("clone-snapshot");
    clone->createSnapshot(clone_snap);

    waitForThisBackendWrite(*clone);

    const std::string pattern3("after-clone-snapshot");

    writeToVolume(*clone,
                  0,
                  clone->getClusterSize(),
                  pattern3);

    checkVolume(*clone,
                0,
                clone->getClusterSize(),
                pattern3);

    restoreSnapshot(*clone,
                    clone_snap);

    checkVolume(*clone,
                0,
                clone->getClusterSize(),
                pattern2);
}
Esempio n. 4
0
    VanillaVolumeConfigParameters
    make_volume_params(const be::BackendTestSetup::WithRandomNamespace& wrns)
    {
        const VolumeSize vsize(CachePage::capacity() *
                               10 *
                               default_cluster_size());

        return VanillaVolumeConfigParameters(VolumeId(wrns.ns().str()),
                                             wrns.ns(),
                                             vsize,
                                             new_owner_tag())
            .metadata_backend_config(metadata_backend_config())
            .metadata_cache_capacity(1);
    }
TEST_P(BigReadWriteTest, bigReadsOnEmpty)
{
    auto ns_ptr = make_random_namespace();

    SharedVolumePtr v = newVolume(VolumeId("volume1"),
                          ns_ptr->ns());

    size_t csz = v->getClusterSize();
    const std::string pattern(csz,'\0');
    size_t scoMul = v->getSCOMultiplier();

    for(size_t i = 0; i < scoMul; ++i)
    {
        checkVolume(*v,0, csz*scoMul, pattern);
    }
}
TEST_P(BigReadWriteTest, OneBigWriteOneBigRead)
{
    auto ns_ptr = make_random_namespace();

    SharedVolumePtr v = newVolume(VolumeId("volume1"),
                                  ns_ptr->ns());

    SCOPED_BLOCK_BACKEND(*v);

    size_t csz = v->getClusterSize();

    const std::string pattern(csz,'a');
    size_t scoMul = v->getSCOMultiplier();
    writeToVolume(*v, 0, csz * scoMul, pattern);

    // Stop here to manually delete sco's to check error handling
    checkVolume(*v,0, csz*scoMul, pattern);

}
TEST_P(SnapshotRestoreTest, RestoreAndWriteAgain1)
{
    auto ns_ptr = make_random_namespace();
    SharedVolumePtr v = newVolume(VolumeId("volume1"),
                          ns_ptr->ns(),
                          VolumeSize(1 << 26),
                          SCOMultiplier(1));

    const std::string pattern("e-manual");

    v->createSnapshot(SnapshotName("snap1"));
    waitForThisBackendWrite(*v);

    writeToVolume(*v, 0, 5 * 4096, pattern);
    waitForThisBackendWrite(*v);

    restoreSnapshot(*v,"snap1");

    writeToVolume(*v, 0, 4*4096, pattern);
    waitForThisBackendWrite(*v);
    checkCurrentBackendSize(*v);
}
TEST_P(SnapshotRestoreTest, HaltOnError)
{
    auto ns_ptr = make_random_namespace();
    SharedVolumePtr v = newVolume(VolumeId("volume1"),
                          ns_ptr->ns());

    const std::string pattern1("blah");

    const TLogId tlog_id(v->getSnapshotManagement().getCurrentTLogId());

    writeToVolume(*v, 0, 4096, pattern1);
    v->createSnapshot(SnapshotName("snap1"));
    waitForThisBackendWrite(*v);

    EXPECT_THROW(restoreSnapshot(*v, "snap42"),
                 std::exception);
    EXPECT_FALSE(v->is_halted());

    v->getBackendInterface()->remove(boost::lexical_cast<std::string>(tlog_id));
    EXPECT_THROW(restoreSnapshot(*v, "snap1"),
                 std::exception);
    EXPECT_TRUE(v->is_halted());
}
Esempio n. 9
0
bool
Backup::create_backup_volume()
{
    LOG_INFO(__FUNCTION__);
    // Need and AssertLocked here
    VERIFY(not target_volume_);
    VERIFY(source_volume_config.get());
    api::getManagementMutex().assertLocked();

    // We check whether the source is a Normal volume
    boost::optional<VolumeConfig::WanBackupVolumeRole> role;
    VERIFY(not role);

    switch(source_volume_config->wan_backup_volume_role_)
    {
    case VolumeConfig::WanBackupVolumeRole::WanBackupNormal:
        if(start_snapshot_)
        {
            LOG_INFO("Incremental backup of a normal volume");
            role = VolumeConfig::WanBackupVolumeRole::WanBackupIncremental;
        }
        else
        {
            LOG_INFO("Complete backup of a normal volume");
            role = VolumeConfig::WanBackupVolumeRole::WanBackupBase;
        }
        break;
    case VolumeConfig::WanBackupVolumeRole::WanBackupBase:
        if(start_snapshot_)
        {
            LOG_INFO("Incremental backup of a backup volume");
            role = VolumeConfig::WanBackupVolumeRole::WanBackupIncremental;
        }
        else
        {
            LOG_INFO("Complete backup of a normal volume");
            role = VolumeConfig::WanBackupVolumeRole::WanBackupBase;
        }
        break;

    case VolumeConfig::WanBackupVolumeRole::WanBackupIncremental:
        if(start_snapshot_)
        {
            LOG_INFO("Incremental backup of a incremental volume");
            role = VolumeConfig::WanBackupVolumeRole::WanBackupIncremental;
        }
        else
        {
            std::vector<SnapshotNum> snaps;
            source_snapshot_persistor->getAllSnapshots(snaps);
            VERIFY(snaps.size() >= 2);
            start_snapshot_ = source_snapshot_persistor->getSnapshotName(snaps[0]);
            LOG_INFO("Complete backup of a incremental volume, created start snapshot " << *start_snapshot_);
            role = VolumeConfig::WanBackupVolumeRole::WanBackupIncremental;
        }
        break;
    }

    VERIFY(role);

    LOG_INFO("Creating new volume in the target with role " << *role);
    try
    {
        boost::this_thread::interruption_point();

        TODO("AR: consider OwnerTag")

        const auto params =
            WriteOnlyVolumeConfigParameters(VolumeId(source_volume_config->getNS().str()),
                                            Namespace(target_namespace),
                                            VolumeSize(source_volume_config->lba_count() *
                                                       source_volume_config->lba_size_),
                                            *role,
                                            OwnerTag(1))
            .lba_size(source_volume_config->lba_size_)
            .cluster_multiplier(source_volume_config->cluster_mult_)
            .sco_multiplier(source_volume_config->sco_mult_);

        target_volume_.reset(api::createNewWriteOnlyVolume(params));
    }
    CATCH_STD_ALL_LOG_RETHROW("problem creating WriteOnlyVolume");

    LOG_INFO("Created new volume in the target -- name is the namespace of the source" << source_volume_config->getNS());

    if(start_snapshot_)
    {
        LOG_INFO("Just created a volume and start snapshot was given... we create a snapshot in the beginning of the volume");
        const SnapshotNum start_snapshot_num =
            source_snapshot_persistor->getSnapshotNum(*start_snapshot_);
        const SnapshotName& start_snapshot_name = *start_snapshot_;

        const UUID
            start_snapshot_uuid(source_snapshot_persistor->getUUID(start_snapshot_num));

        boost::this_thread::interruption_point();
        api::createSnapshot(target_volume_.get(),
                            SnapshotMetaData(),
                            &start_snapshot_name,
                            start_snapshot_uuid);

        WAIT_FOR_THIS_VOLUME_WRITE(target_volume_.get());

        VERIFY(api::isVolumeSyncedUpTo(target_volume_.get(),
                                       start_snapshot_name));
        if(*start_snapshot_ == end_snapshot_name)
        {
            LOG_INFO("start_snapshot == end_snapshot " << end_snapshot_name << " so exiting now");

            while(not api::isVolumeSyncedUpTo(target_volume_.get(),
                                              *start_snapshot_))
            {
                LOG_INFO("Waiting for the volume to finish writing to the backend, sleeping another 10 seconds");
                sleep(10);
            }

            status_.finish();

            LOG_INFO("Finished the Backup");
            return false;
        }
    }
    else
    {
        LOG_INFO("Is a full backup to the newly created volume");
    }
    return true;
}
TEST_P(SnapshotRestoreTest, SimpleRestore)
{
    auto ns_ptr = make_random_namespace();
    SharedVolumePtr v = newVolume(VolumeId("volume1"),
                          ns_ptr->ns());

    const std::string pattern1("Frederik");

    writeToVolume(*v, 0, 4096, pattern1);
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snap1"));

    const std::string pattern2("Frederik");

    writeToVolume(*v, 0, 4096, pattern2);
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snap2"));


    const std::string pattern3("Arne");

    writeToVolume(*v, 0, 4096, pattern3);
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snap3"));

    const std::string pattern4("Bart");

    writeToVolume(*v, 0, 4096, pattern4);
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snap4"));

    const std::string pattern5("Wouter");
    writeToVolume(*v, 0, 4096, pattern5);

    checkVolume(*v,0,4096,pattern5);
    waitForThisBackendWrite(*v);

    EXPECT_NO_THROW(restoreSnapshot(*v,
                                    "snap4"));

    checkVolume(*v,0,4096,pattern4);
    writeToVolume(*v, 0, 4096, "Bollocks");
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snapper"));
    waitForThisBackendWrite(*v);

    EXPECT_NO_THROW(restoreSnapshot(*v,
                                    "snap3"));

    checkVolume(*v,0,4096,pattern3);
    writeToVolume(*v, 0, 4096, "Bollocks");
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snapper"));
    waitForThisBackendWrite(*v);

    EXPECT_NO_THROW(restoreSnapshot(*v,
                                    "snap2"));

    checkVolume(*v,0,4096,pattern2);
    writeToVolume(*v, 0, 4096, "Bollocks");
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snapper"));
    waitForThisBackendWrite(*v);

    EXPECT_NO_THROW(restoreSnapshot(*v,
                                    "snap1"));

    checkVolume(*v,0,4096,pattern1);
    writeToVolume(*v, 0, 4096, "Bollocks");
    waitForThisBackendWrite(*v);
    v->createSnapshot(SnapshotName("snapper"));
    waitForThisBackendWrite(*v);
    checkCurrentBackendSize(*v);
}