int StartGenConversion()

in host/AzureRecoveryLib/win32/RecoveryHelpers.cpp [591:767]


int StartGenConversion()
{
    using namespace AzureRecovery;

    TRACE_FUNC_BEGIN;
    int retcode = E_RECOVERY_SUCCESS;

    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 update bcd recodrds 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 gen conversion on OS install path: %s.\n",
                srcOsInstallPath.str().c_str());

            SetOSVersionDetails(srcOsInstallPath.str());

            // TODO: UEFI commands need not be 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;
                }

                // Enable serial console on BIOS BCD Path as the VM has been converted.
                if (EnableSerialConsole(srcOsInstallPath.str()) != ERROR_SUCCESS)
                {
                    // Log within HydrationLogs.
                    errStream << "Could not update serial console for the VM. ";

                    // Do not fail.
                }

                if (!UpdateBIOSBootRecordsOnOSDisk(
                    srcOsInstallPath.str(),
                    activePartitionDrive,
                    (std::string) "BIOS",
                    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;
                }

                bool isWin2k8 = false;
                OSVersion osVersion;
                if (GetOsVersion(osVersion)) {
                    isWin2k8 = ((osVersion.major == 6) && (osVersion.minor == 0));
                }

                // Since gen-conversion is a critical failure in protection service, using alternate retCode so hydration doesn't fail
                // if any of the registry changes fail.
                int regRetCode = 0;
                std::stringstream regErrStr;

                // Make registry changes, enable DHCP and install guest agent.
                bool bSuccess = MakeRegistryChangesForMigration(srcOsInstallPath.str(),
                    srcOsVol,
                    regRetCode,
                    curTaskDesc,
                    regErrStr,
                    isWin2k8);

                if (!IsDotNetFxVersionPresent(srcOsVol))
                {
                    TRACE_INFO("No installation of version 4.0+ of Microsoft.NET found.\n");
                    
                    if (retcode == 0)
                    {
                        errStream << "Windows VM Agent requires .NET version 4.0+ .";
                        retcode = E_RECOVERY_DOTNET_FRAMEWORK_INCOMPATIBLE;
                    }
                }

                if (!bSuccess)
                {
                    // Log the error and ignore.
                    TRACE_ERROR("Couldn't modify the registry settings for Gen2 VM. %s\n", regErrStr.str().c_str());
                }

                errStream << "Successfully modified the OS installation: "
                    << srcOsInstallPath.str()
                    << ".";
            }
            else
            {
                TRACE_WARNING("Not a UEFI VM, nothing to update.");

                errStream << "Not a Gen2 VM. Nothing to modify in 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;
}