void HostRecoveryManager::GetRecoveryInfo()

in host/common/hostrecoverymanager.cpp [227:373]


void HostRecoveryManager::GetRecoveryInfo(bool & bIsHydrationWorkflow,
    bool& bSystemUuidChanged,
    bool& bHypervisorChanged,
    bool& bIsAzureVm,
    bool& bVmTypeChanged,
    bool& bIsFailoverDetected,
    QuitFunction_t qf)
{
    DebugPrintf(SV_LOG_DEBUG, "Entering %s\n", FUNCTION_NAME);

    bIsHydrationWorkflow = false;
    bHypervisorChanged = false;
    bSystemUuidChanged = false;
    bIsAzureVm = false;
    bVmTypeChanged = false;

    LocalConfigurator   lc;

    // Recovery is only meaningful for mobility agent
    if (!lc.isMobilityAgent()) {
        DebugPrintf(SV_LOG_DEBUG, "Not running as mobility agent.. skipping recovery check\n");
        return;
    }

#ifdef SV_WINDOWS
    //
    // ### Hydration ###
    ///
    // Check if it is hydration workflow.
    // 
    bIsHydrationWorkflow = ::IsRecoveryInProgress();
    if (bIsHydrationWorkflow)
    {
        DebugPrintf(SV_LOG_INFO,
            "Hydration has happened. Recovery is in pogress.");

        DebugPrintf(SV_LOG_DEBUG, "Exiting %s\n", FUNCTION_NAME);
        return;
    }
#endif
    //
    // ### No-Hydration / Clone ###
    // 

    //
    // Check if the Persisted VM info availability
    //
    std::string persistedHypervisorName;
    std::string persistedSystemUUID;
    bool persistedIsAzureVm;

    if (GetPersistedVMInfo(persistedHypervisorName, persistedSystemUUID, persistedIsAzureVm))
    {
        DebugPrintf(SV_LOG_INFO,
            "Persisted VM info available: Hypervisor: %s, System UUID: %s, IsAzureVm %d\n",
            persistedHypervisorName.c_str(),
            persistedSystemUUID.c_str(),
            persistedIsAzureVm);
    }
    else
    {
        DebugPrintf(SV_LOG_INFO,
            "Persisted VM info not available. It might not be a recovery.\n");

        return;
    }

    //
    // Discover the System UUID and Hypervisor
    //
    string systemUUID = GetSystemUUID();

    // Skip recovery detection if System UUID is empty.
    if (systemUUID.empty()) {
        DebugPrintf(SV_LOG_ERROR, "IsRecoveryInProgress: Could not retrieve System UUID or got empty UUID.");
        return;
    }

    if (boost::iequals(systemUUID, INVALID_UUID)) {
        DebugPrintf(SV_LOG_ERROR, "IsRecoveryInProgress: Got Invalid UUID.");
        return;
    }

    string hypervisor, hypervisorversion;
    if (!IsVirtual(hypervisor, hypervisorversion))
    {
        hypervisor = PHYSICALMACHINE;
    }

    bSystemUuidChanged = !boost::iequals(systemUUID, persistedSystemUUID);

    if (persistedHypervisorName.empty() ||
        persistedSystemUUID.empty() ||
        boost::iequals(persistedSystemUUID, INVALID_UUID) ||
        !bSystemUuidChanged) {
        DebugPrintf(SV_LOG_DEBUG, "Exiting %s\n", FUNCTION_NAME);
        return;
    }

    //
    // Compare discovered VM info with persisted values to detect the VM recovery.
    // On Vmware if system UUID changes it is a clone
    // On failover if system UUID changes
    //
    bIsAzureVm = IsAzureVirtualMachine();

    // If hypervisor has not changed, it means it is a clone except when 
    //      Hyper-v VM is migrated to Azure,
    //      Clone of Azure VM after failover from on-prem - [Migraton of Azure VM not supported using V2A,
    //          use A2A and such recovery is handled in AzureVmRecoveryManager ]
    //      Azure stack to Azure migration - [ this is not handled by this logic.
    //          it is detected as clone and that is fine as no failback is supported ]
    //      AVS scenario involved where the decision is made based on the FailoverVmBiosid received from rcm
    //          it is detected as failover if the rcm received biosid matches with the current system biosid
    // Note that the only difference between clone and failover is to set the new hostId as BIOS-ID and the source control plane
    // for the AVS scenario
    // (see CompleteRecovery()). Except for the V2A Legacy there is no such requirement in other providers. 
    bHypervisorChanged = !boost::iequals(hypervisor, persistedHypervisorName);
    bVmTypeChanged = (bIsAzureVm != persistedIsAzureVm);

    DebugPrintf(SV_LOG_INFO,
        "Current VM Info: Hypervisor: %s, System UUID: %s, IsAzureVm %d\n",
        hypervisor.c_str(),
        systemUUID.c_str(),
        bIsAzureVm);

    string failoverVmBiosId = lc.getFailoverVmBiosId();
    if (!failoverVmBiosId.empty()){
        DebugPrintf(SV_LOG_DEBUG, "Failover Vm BiosId is %s.\n",
            failoverVmBiosId.c_str());
    }

    if ( bVmTypeChanged || (bHypervisorChanged || 
        (!failoverVmBiosId.empty() && (boost::iequals(failoverVmBiosId, systemUUID) ||
        boost::iequals(failoverVmBiosId, BiosID::GetByteswappedBiosID(systemUUID)))) ||
        (IsAzureStackVirtualMachine() && HasAzureStackHubFailoverTag(qf)))) {
        bIsFailoverDetected = true;
        DebugPrintf(SV_LOG_ALWAYS, "Failover Detected Persisted UUID: %s CurrentUUID: %s\n", persistedSystemUUID.c_str(), systemUUID.c_str());
    }
    else
    {
        DebugPrintf(SV_LOG_ALWAYS, "Clone Detected Persisted UUID: %s CurrentUUID: %s\n", persistedSystemUUID.c_str(), systemUUID.c_str());
    }

    DebugPrintf(SV_LOG_DEBUG, "Exiting %s\n", FUNCTION_NAME);
    return;
}