VirtualBox

Changeset 23669 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Oct 10, 2009 3:02:01 AM (15 years ago)
Author:
vboxsync
Message:

Main: Live migration coding.

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp

    r23663 r23669  
    6060    RTSOCKET            mhSocket;
    6161    uint64_t            moffStream;
     62    bool volatile       mfStopReading;
    6263    /** @} */
    6364
     
    6768        , mhSocket(NIL_RTSOCKET)
    6869        , moffStream(UINT64_MAX / 2)
     70        , mfStopReading(false)
    6971    {
    7072    }
     
    98100    IMachine           *mpMachine;
    99101    void               *mpvVMCallbackTask;
     102    PRTTCPSERVER        mhServer;
    100103    int                 mRc;
    101104
     
    104107        , mpMachine(pMachine)
    105108        , mpvVMCallbackTask(NULL)
     109        , mhServer(NULL)
    106110        , mRc(VINF_SUCCESS)
    107111    {
     
    164168    if (RT_FAILURE(rc))
    165169        LogRel(("Migration: RTTcpWrite(,ACK,) -> %Rrc\n", rc));
     170    RTTcpFlush(pState->mhSocket);
    166171    return rc;
    167172}
     
    173178    if (RT_FAILURE(rc))
    174179        LogRel(("Migration: RTTcpWrite(,NACK,) -> %Rrc\n", rc));
     180    RTTcpFlush(pState->mhSocket);
    175181    return rc;
    176182}
     
    182188 * @returns S_OK on ACK, E_FAIL+setError() on failure or NACK.
    183189 * @param   pState              The live migration source state.
     190 * @param   pszNAckMsg          Optional NACK message.
    184191 *
    185192 * @remarks the setError laziness forces this to be a Console member.
    186193 */
    187194HRESULT
    188 Console::migrationSrcReadACK(MigrationStateSrc *pState)
     195Console::migrationSrcReadACK(MigrationStateSrc *pState, const char *pszNAckMsg /*= NULL*/)
    189196{
    190197    char szMsg[128];
     
    192199    if (RT_FAILURE(vrc))
    193200        return setError(E_FAIL, tr("Failed reading ACK: %Rrc"), vrc);
    194     if (strcmp(szMsg, "ACK\n"))
    195     {
    196         if (strcmp(szMsg, "NACK\n"))
    197             return setError(E_FAIL, "NACK");
     201    if (strcmp(szMsg, "ACK"))
     202    {
     203        if (!strcmp(szMsg, "NACK"))
     204            return setError(E_FAIL, pszNAckMsg ? pszNAckMsg : "NACK");
    198205        return setError(E_FAIL, tr("Expected ACK or NACK, got '%s'"), szMsg);
    199206    }
     
    246253{
    247254    MigrationState *pState = (MigrationState *)pvUser;
    248     int rc = RTTcpRead(pState->mhSocket, pvBuf, cbToRead, pcbRead);
    249     if (RT_SUCCESS(rc))
    250     {
    251         pState->moffStream += pcbRead ? *pcbRead : cbToRead;
    252         return VINF_SUCCESS;
    253     }
    254     return rc;
     255
     256    for (;;)
     257    {
     258        int rc = RTTcpSelectOne(pState->mhSocket, 30); /** @todo fix this polling mess. */
     259        if (RT_SUCCESS(rc))
     260        {
     261            rc = RTTcpRead(pState->mhSocket, pvBuf, cbToRead, pcbRead);
     262            if (RT_FAILURE(rc))
     263                return rc;
     264            pState->moffStream += pcbRead ? *pcbRead : cbToRead;
     265            return VINF_SUCCESS;
     266        }
     267        if (rc != VERR_TIMEOUT)
     268            return rc;
     269        if (pState->mfStopReading)
     270            return VERR_EOF;
     271    }
    255272}
    256273
     
    289306static DECLCALLBACK(int) migrationTcpOpClose(void *pvUser)
    290307{
     308    MigrationState *pState = (MigrationState *)pvUser;
     309    ASMAtomicWriteBool(&pState->mfStopReading, true);
    291310    return VINF_SUCCESS;
    292311}
     
    336355    { AutoWriteLock autoLock(); }
    337356
     357    BOOL fCanceled = TRUE;
     358    HRESULT hrc = pState->mptrProgress->COMGETTER(Canceled)(&fCanceled);
     359    if (FAILED(hrc))
     360        return hrc;
     361    if (fCanceled)
     362        return setError(E_FAIL, tr("canceled"));
     363
    338364    /*
    339365     * Try connect to the destination machine.
     
    341367     */
    342368    int vrc = RTTcpClientConnect(pState->mstrHostname.c_str(), pState->muPort, &pState->mhSocket);
    343     if (RT_SUCCESS(vrc))
     369    if (RT_FAILURE(vrc))
    344370        return setError(E_FAIL, tr("Failed to connect to port %u on '%s': %Rrc"),
    345371                        pState->muPort, pState->mstrHostname.c_str(), vrc);
     
    360386
    361387    /* ACK */
    362     HRESULT hrc = migrationSrcReadACK(pState);
     388    hrc = migrationSrcReadACK(pState, tr("Invalid password"));
    363389    if (FAILED(hrc))
    364390        return hrc;
     
    407433    HRESULT hrc = pState->mptrConsole->migrationSrc(pState);
    408434    pState->mptrProgress->notifyComplete(hrc);
     435
     436    if (    FAILED(hrc)
     437        &&  pState->mptrConsole->mMachineState == MachineState_Saving)
     438    {
     439        VMSTATE enmVMState = VMR3GetState(pState->mpVM);
     440        switch (enmVMState)
     441        {
     442            case VMSTATE_RUNNING:
     443            case VMSTATE_RUNNING_LS:
     444            case VMSTATE_DEBUGGING:
     445            case VMSTATE_DEBUGGING_LS:
     446            case VMSTATE_POWERING_OFF:
     447            case VMSTATE_POWERING_OFF_LS:
     448            case VMSTATE_RESETTING:
     449            case VMSTATE_RESETTING_LS:
     450                pState->mptrConsole->setMachineState(MachineState_Running);
     451                break;
     452            case VMSTATE_GURU_MEDITATION:
     453            case VMSTATE_GURU_MEDITATION_LS:
     454                pState->mptrConsole->setMachineState(MachineState_Stuck);
     455                break;
     456            default:
     457                AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState)));
     458            case VMSTATE_SUSPENDED:
     459            case VMSTATE_SUSPENDED_LS:
     460            case VMSTATE_SUSPENDING:
     461            case VMSTATE_SUSPENDING_LS:
     462            case VMSTATE_SUSPENDING_EXT_LS:
     463                pState->mptrConsole->setMachineState(MachineState_Paused);
     464                break;
     465        }
     466    }
    409467
    410468    if (pState->mhSocket != NIL_RTSOCKET)
     
    480538    pState->mptrProgress = ptrMigrateProgress;
    481539
    482     int vrc = RTThreadCreate(NULL, Console::migrationSrcThreadWrapper, pState, 0 /*cbStack*/,
     540    int vrc = RTThreadCreate(NULL, Console::migrationSrcThreadWrapper, (void *)pState, 0 /*cbStack*/,
    483541                             RTTHREADTYPE_EMULATION, 0 /*fFlags*/, "Migrate");
    484542    if (RT_SUCCESS(vrc))
     543    {
     544        hrc = setMachineState(MachineState_Saving);
     545        if (SUCCEEDED(hrc))
     546            ptrMigrateProgress.queryInterfaceTo(aProgress);
     547        else
     548            ptrMigrateProgress->Cancel();
     549    }
     550    else
     551    {
    485552        delete pState;
    486 
    487     return E_FAIL;
     553        hrc = setError(E_FAIL, tr("RTThreadCreate -> %Rrc"), vrc);
     554    }
     555
     556    return hrc;
    488557}
    489558
     
    496565 * @param   pVM                 The VM handle
    497566 * @param   pMachine            The IMachine for the virtual machine.
     567 * @param   fStartPaused        Whether to start it in the Paused (true) or
     568 *                              Running (false) state,
    498569 * @param   pvVMCallbackTask    The callback task pointer for
    499570 *                              stateProgressCallback().
    500571 */
    501572int
    502 Console::migrationDst(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask)
     573Console::migrationDst(PVM pVM, IMachine *pMachine, bool fStartPaused, void *pvVMCallbackTask)
    503574{
    504575    /*
     
    515586        return VERR_GENERAL_FAILURE;
    516587    Utf8Str strPassword(bstrPassword);
     588    strPassword.append('\n');           /* To simplify password checking. */
    517589
    518590    Utf8Str strBind("");
    519591    /** @todo Add a bind address property. */
    520592    const char *pszBindAddress = strBind.isEmpty() ? NULL : strBind.c_str();
     593
    521594
    522595    /*
     
    563636             */
    564637            MigrationStateDst State(this, pVM, pMachine);
    565             State.mstrPassword = strPassword;
     638            State.mstrPassword      = strPassword;
     639            State.mhServer          = hServer;
     640            State.mpvVMCallbackTask = pvVMCallbackTask;
    566641
    567642            vrc = RTTcpServerListen(hServer, Console::migrationDstServeConnection, &State);
    568643            if (vrc == VERR_TCP_SERVER_STOP)
    569644                vrc = State.mRc;
    570             if (RT_FAILURE(vrc))
     645            if (RT_SUCCESS(vrc))
     646            {
     647                if (fStartPaused)
     648                    setMachineState(MachineState_Paused);
     649                else
     650                    vrc = VMR3Resume(pVM);
     651            }
     652            else
     653            {
    571654                LogRel(("Migration: RTTcpServerListen -> %Rrc\n", vrc));
     655            }
    572656        }
    573657
     
    586670Console::migrationDstServeConnection(RTSOCKET Sock, void *pvUser)
    587671{
    588     MigrationStateDst *pState   = (MigrationStateDst *)pvUser;
     672    MigrationStateDst *pState = (MigrationStateDst *)pvUser;
     673    pState->mhSocket = Sock;
    589674
    590675    /*
     
    603688     * this is the last connection attempt).
    604689     */
    605     pState->mstrPassword.append('\n');
    606690    const char *pszPassword = pState->mstrPassword.c_str();
    607691    unsigned    off = 0;
     
    625709    if (RT_FAILURE(vrc))
    626710        return vrc;
    627     RTTcpServerShutdown((PRTTCPSERVER)pvUser);
     711    RTTcpServerShutdown(pState->mhServer);
    628712
    629713    /*
    630714     * Command processing loop.
    631715     */
    632     pState->mhSocket = Sock;
    633716    for (;;)
    634717    {
     
    671754        }
    672755    }
     756
    673757    pState->mhSocket = NIL_RTSOCKET;
    674 
    675758    return VERR_TCP_SERVER_STOP;
    676759}
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r23664 r23669  
    46144614    }
    46154615
     4616    /* test and clear the LiveMigrationTarget property  */
     4617    BOOL fLiveMigrationTarget;
     4618    rc = mMachine->COMGETTER(LiveMigrationTarget)(&fLiveMigrationTarget);
     4619    CheckComRCReturnRC(rc);
     4620    if (fLiveMigrationTarget)
     4621    {
     4622        rc = mMachine->COMSETTER(LiveMigrationTarget)(FALSE);
     4623        CheckComRCReturnRC(rc);
     4624    }
     4625
    46164626    /* create a progress object to track progress of this operation */
    46174627    ComObjPtr<Progress> powerupProgress;
     
    46204630    if (mMachineState == MachineState_Saved)
    46214631        progressDesc = tr("Restoring virtual machine");
     4632    else if (fLiveMigrationTarget)
     4633        progressDesc = tr("Migrating virtual machine");
    46224634    else
    46234635        progressDesc = tr("Starting virtual machine");
     
    46384650    if (mMachineState == MachineState_Saved)
    46394651        task->mSavedStateFile = savedStateFile;
    4640 
    4641     /* test and clear the LiveMigrationTarget property  */
    4642     rc = mMachine->COMGETTER(LiveMigrationTarget)(&task->mLiveMigrationTarget);
    4643     CheckComRCReturnRC(rc);
    4644     if (task->mLiveMigrationTarget)
    4645     {
    4646         rc = mMachine->COMSETTER(LiveMigrationTarget)(FALSE);
    4647         CheckComRCReturnRC(rc);
    4648     }
     4652    task->mLiveMigrationTarget = fLiveMigrationTarget;
    46494653
    46504654    /* Reset differencing hard disks for which autoReset is true */
     
    47264730     * any error reporting and appropriate state change! */
    47274731
    4728     if (mMachineState == MachineState_Saved)
     4732    if (   mMachineState == MachineState_Saved
     4733        || fLiveMigrationTarget)
    47294734        setMachineState(MachineState_Restoring);
    47304735    else
     
    67436748                }
    67446749                else if (task->mLiveMigrationTarget)
     6750                {
    67456751                    /* -> ConsoleImpl-LiveMigration.cpp */
    6746                     vrc = console->migrationDst(pVM, pMachine, static_cast<VMProgressTask*>(task.get()));
     6752                    vrc = console->migrationDst(pVM, pMachine, task->mStartPaused,
     6753                                                static_cast<VMProgressTask*>(task.get()));
     6754                    if (RT_FAILURE(vrc))
     6755                        VMR3PowerOff(pVM);
     6756                }
    67476757                else if (task->mStartPaused)
    67486758                    /* done */
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r23663 r23669  
    518518    static DECLCALLBACK(int)    migrationSrcThreadWrapper(RTTHREAD hThread, void *pvUser);
    519519    HRESULT                     migrationSrc(MigrationStateSrc *pState);
    520     HRESULT                     migrationSrcReadACK(MigrationStateSrc *pState);
     520    HRESULT                     migrationSrcReadACK(MigrationStateSrc *pState, const char *pszNAckMsg = NULL);
    521521    HRESULT                     migrationSrcSubmitCommand(MigrationStateSrc *pState, const char *pszCommand);
    522     int                         migrationDst(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask);
     522    int                         migrationDst(PVM pVM, IMachine *pMachine, bool fStartPaused, void *pvVMCallbackTask);
    523523    static DECLCALLBACK(int)    migrationDstServeConnection(RTSOCKET Sock, void *pvUser);
    524524    /** @} */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette