int StartMigration()

in host/AzureRecoveryLib/win32/RecoveryHelpers.cpp [417:579]


int StartMigration()
{
    using namespace AzureRecovery;

    TRACE_FUNC_BEGIN;
    int retcode = 0;

    std::stringstream errStream;
    std::string errorMessage;
    std::string curTaskDesc;
    do
    {
        curTaskDesc = TASK_DESCRIPTIONS::PREPARE_DISKS;
        if (!OnlineDisks(errorMessage))
        {
            // Ignore any error here. If OS disk online fails 
            // then the later logic will anyway result in failure.

            TRACE_ERROR(
                "Disk online failed for one of the disks. %s.\n",
                errorMessage.c_str());
        }

        std::list<std::string> osVolumes;
        curTaskDesc = TASK_DESCRIPTIONS::MOUNT_SYSTEM_PARTITIONS;
        if (!DiscoverSourceOSVolumes(osVolumes, errorMessage))
        {
            retcode = E_RECOVERY_VOL_NOT_FOUND;

            errStream << "Could not prepare Source OS install path on Hydration VM.( "
                << errorMessage
                << " )";

            TRACE_ERROR("%s\n", errStream.str().c_str());

            //
            // OS volume is not identified, print all the partitions details.
            //
            PrintAllDiskPartitions();

            RecoveryStatus::Instance().SetStatusErrorCode(
                retcode,
                "OS Volume");

            break;
        }
        BOOST_ASSERT(osVolumes.size() > 0);

        // Do hydration for all the OS volumes discovered.
        BOOST_FOREACH(const std::string& srcOsVol, osVolumes)
        {
            std::stringstream srcOsInstallPath;
            srcOsInstallPath
                << boost::trim_right_copy_if(srcOsVol, boost::is_any_of(DIRECOTRY_SEPERATOR))
                << SysConstants::DEFAULT_SYSTEM32_DIR;

            TRACE_INFO("Performing hydration on OS install path: %s.\n",
                srcOsInstallPath.str().c_str());

            SetOSVersionDetails(srcOsInstallPath.str());
            std::string osVersion = RecoveryStatus::Instance().GetUpdate().OsDetails;

            // Check if it is Win2k8, if so then AutoMount should be disabled.
            bool isWin2k8 = boost::starts_with(osVersion,
                RegistryConstants::WIN2K8_VERSION_PREFIX);

            // TODO: UEFI commands need not to run on every OS volume found.
            if (AzureRecoveryConfig::Instance().IsUEFI())
            {
                std::string activePartitionDrive;
                if (!PrepareActivePartitionDrive(
                    activePartitionDrive,
                    errorMessage))
                {
                    retcode = E_RECOVERY_COULD_NOT_PREPARE_ACTIVE_PARTITION_DRIVE;

                    errStream << "Could not prepare active partition drive for BCD update. ( "
                        << errorMessage
                        << " )";

                    TRACE_ERROR("%s\n", errStream.str().c_str());

                    PrintAllDiskPartitions();

                    break;
                }
                if (!UpdateBIOSBootRecordsOnOSDisk(
                    srcOsInstallPath.str(),
                    activePartitionDrive,
                    (std::string) "ALL",
                    errorMessage))
                {
                    retcode = E_RECOVERY_COULD_NOT_UPDATE_BCD;

                    errStream << "Could not update BIOS boot records on active partition. ( "
                        << errorMessage
                        << " )";

                    TRACE_ERROR("%s\n", errStream.str().c_str());

                    PrintAllDiskPartitions();

                    break;
                }
            }

            if (EnableSerialConsole(srcOsInstallPath.str()) != ERROR_SUCCESS)
            {
                // Log within HydrationLogs.
                std::stringstream scErrStream;
                scErrStream << "Could not update serial console for the VM. ";

                TRACE_ERROR("%s\n", scErrStream.str().c_str());

                // Do not fail.
            }

            bool bSuccess = MakeRegistryChangesForMigration(srcOsInstallPath.str(),
                srcOsVol,
                retcode,
                curTaskDesc,
                errStream,
                isWin2k8);

            if (!IsDotNetFxVersionPresent(srcOsVol))
            {
                TRACE_INFO("No installation of version 4.0+ of Microsoft.NET found.\n");

                if (retcode == 0)
                {
                    retcode = E_RECOVERY_DOTNET_FRAMEWORK_INCOMPATIBLE;
                }
            }

            if (!errStream.str().empty())
            {
                // Formatting if errStream already exists. 
                errStream << ". ";
            }

            errStream << (bSuccess ? "Successfully modified" : "Could not modify")
                << " the OS installation: "
                << srcOsInstallPath.str()
                << ".";
        }

        curTaskDesc = TASK_DESCRIPTIONS::UPLOAD_LOG;
    } while (false);

    // Set error details.
    RecoveryStatus::Instance().UpdateErrorDetails(
        retcode,
        errStream.str());

    // Update progress.
    RecoveryStatus::Instance().UpdateProgress(100,
        retcode == 0 ?
        Recovery_Status::ExecutionSuccess :
        Recovery_Status::ExecutionFailed,
        curTaskDesc);

    return retcode;
}