int StartRecovery()

in host/AzureRecoveryLib/win32/RecoveryHelpers.cpp [130:405]


int StartRecovery()
{
    using namespace AzureRecovery;

    TRACE_FUNC_BEGIN;
    int retcode = 0;

    std::stringstream errStream;
    std::string srcOsInstallPath;
    std::string errorMessage;
    std::string curTaskDesc;

    do
    {
        curTaskDesc = TASK_DESCRIPTIONS::PREPARE_DISKS;
        if (!VerifyDisks(errorMessage))
        {
            //
            // Not failing the operation here, if required disk is not available then
            // the next step will throw error.
            //
            /*retcode = E_RECOVERY_DISK_NOT_FOUND;

            errStream << "Error verifying disks. ( " << errorMessage << " )";

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

            break;*/
        }

        curTaskDesc = TASK_DESCRIPTIONS::MOUNT_SYSTEM_PARTITIONS;
        if (!PrepareSourceSystemPath(srcOsInstallPath, 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();

            break;
        }

        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,
                activePartitionDrive,
                std::string("ALL"),
                errorMessage))
            {
                retcode = E_RECOVERY_COULD_NOT_UPDATE_BCD;

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

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

                PrintAllDiskPartitions();

                break;
            }
        }

        if (EnableSerialConsole(srcOsInstallPath) != ERROR_SUCCESS)
        {
            // Log within HydrationLogs.
            errStream << "Could not enable serial console for the VM. ";

            TRACE_ERROR("%s\n", errStream.str().c_str());
            // Not a critical failure, continue
        }

        if (!PrepareSourceRegistryHives(srcOsInstallPath, errorMessage))
        {
            retcode = E_RECOVERY_PREP_REG;

            errStream << "Could not prepare the source registry.( "
                << errorMessage
                << " )";

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

        curTaskDesc = TASK_DESCRIPTIONS::CHANGE_BOOT_CONFIG;
        if (!MakeChangesForBootDriversOnRegistry(srcOsInstallPath, errorMessage, retcode))
        {
            errStream << "Could not update required boot drivers on registry.( "
                << errorMessage
                << " )";

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

            break;
        }

        curTaskDesc = TASK_DESCRIPTIONS::CHANGE_SVC_NW_CONFIG;
        if (!MakeChangesForServicesOnRegistry(srcOsInstallPath, errorMessage))
        {
            retcode = E_RECOVERY_SVC_CONFIG;

            errStream << "Could not update required services on registry.( "
                << errorMessage
                << " )";

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

            break;
        }

        bool isWindows2008 = false;

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

        SetOSVersionDetails(srcOsInstallPath);

        DWORD dwSanPolicy = (isWindows2008) ? VDS_SAN_POLICY::VDS_SP_OFFLINE : VDS_SAN_POLICY::VDS_SP_ONLINE;

        if (!SetSANPolicy(errorMessage, dwSanPolicy))
        {
            retcode = E_RECOVERY_SVC_CONFIG;

            errStream << "Could not update SanPolicy on registry.( "
                << errorMessage
                << " )";

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

            break;
        }

        if (!ResetInvolfltParameters(errorMessage))
        {
            retcode = E_RECOVERY_INVOLFLT_DRV;

            errStream << "Could not reset involflt keys in source registry.( "
                << errorMessage
                << " )";

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

            break;
        }

        if (!SetRdpParameters(errorMessage))
        {
            retcode = E_RECOVERY_RDP_ENABLE;

            errStream << "Could not set rdp parameters in source registry.( "
                << errorMessage
                << " )";

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

            break;
        }

        //if (!UpdateNewHostId(errorMessage))
        //{
        //	retcode = E_RECOVERY_HOSTID_UPDATE;

        //	errStream << "Could not update new hostid in source registry.( "
        //		<< errorMessage
        //		<< " )";

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

        //	break;
        //}

        if (!SetBootupScriptEx(errorMessage))
        {
            retcode = E_RECOVERY_BOOTUP_SCRIPT;

            errStream << "Could not add bootup script entries in source registry.( "
                << errorMessage
                << " )";

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

            break;
        }

        std::stringstream wingaErrSteam;
        if (VerifyRegistrySettingsForWinGA(srcOsInstallPath.substr(0, srcOsInstallPath.size() - 17), wingaErrSteam))
        {
            // Not throwing any error since we do not have soft failures in DR.
            errStream << "Guest agent installation was skipped as the VM already has a Guest Agent present. ";
            TRACE_WARNING("%s\n", errStream.str().c_str());

            break;
        }
        else
        {
            if (!AddWindowsGuestAgent(srcOsInstallPath.substr(0, srcOsInstallPath.size() - 16), wingaErrSteam))
            {
                // Log error code and do not fail.
                errStream
                    << "VM has successfully failed over but Guest agent installation has failed"
                    << ". Please manually install the guest agent on the VM. ";

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

                break;
            }
        }

        if (!IsDotNetFxVersionPresent(srcOsInstallPath.substr(0, 3)))
        {
            TRACE_INFO("No installation of version 4.0+ of Microsoft.NET found.\n");
            
            if (retcode == 0)
            {
                retcode = E_RECOVERY_DOTNET_FRAMEWORK_INCOMPATIBLE;
            }
        }

    } while (false);

    curTaskDesc = TASK_DESCRIPTIONS::UNMOUNT_SYSTEM_PARTITIONS;
    if (!ReleaseSourceRegistryHives(errorMessage))
    {
        retcode = E_RECOVERY_CLEANUP;
        errStream << "Could not unload source registry hives loaded for data massaging.( "
            << errorMessage
            << " )";

        TRACE_ERROR("%s\n", errStream.str().c_str());
    }
    else
    {
        errStream << "All steps executed successfuly";
    }

    curTaskDesc = TASK_DESCRIPTIONS::UPLOAD_LOG;

    // Update status info.
    RecoveryStatus::Instance().UpdateErrorDetails(
        retcode,
        errStream.str());

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

    return retcode;
}