VirtualBox

Changeset 35563 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Jan 14, 2011 1:49:23 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
69447
Message:

Main/Console: reorder VM startup activities and make sure as many early failures as possible reach the caller of IMachine::launchVMProcess

File:
1 edited

Legend:

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

    r35481 r35563  
    53575357    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    53585358
    5359     if (Global::IsOnlineOrTransient(mMachineState))
    5360         return setError(VBOX_E_INVALID_VM_STATE,
    5361             tr("The virtual machine is already running or busy (machine state: %s)"),
    5362             Global::stringifyMachineState(mMachineState));
    5363 
    53645359    HRESULT rc = S_OK;
    5365 
    5366     /* the network cards will undergo a quick consistency check */
    5367     for (ULONG slot = 0;
    5368          slot < SchemaDefs::NetworkAdapterCount;
    5369          ++slot)
    5370     {
    5371         ComPtr<INetworkAdapter> pNetworkAdapter;
    5372         mMachine->GetNetworkAdapter(slot, pNetworkAdapter.asOutParam());
    5373         BOOL enabled = FALSE;
    5374         pNetworkAdapter->COMGETTER(Enabled)(&enabled);
    5375         if (!enabled)
    5376             continue;
    5377 
    5378         NetworkAttachmentType_T netattach;
    5379         pNetworkAdapter->COMGETTER(AttachmentType)(&netattach);
    5380         switch (netattach)
    5381         {
    5382             case NetworkAttachmentType_Bridged:
     5360    ComObjPtr<Progress> pPowerupProgress;
     5361    bool fBeganPoweringUp = false;
     5362
     5363    try
     5364    {
     5365        if (Global::IsOnlineOrTransient(mMachineState))
     5366            throw setError(VBOX_E_INVALID_VM_STATE,
     5367                tr("The virtual machine is already running or busy (machine state: %s)"),
     5368                Global::stringifyMachineState(mMachineState));
     5369
     5370        /* test and clear the TeleporterEnabled property  */
     5371        BOOL fTeleporterEnabled;
     5372        rc = mMachine->COMGETTER(TeleporterEnabled)(&fTeleporterEnabled);
     5373        if (FAILED(rc))
     5374            throw rc;
     5375#if 0 /** @todo we should save it afterwards, but that isn't necessarily a good idea. Find a better place for this (VBoxSVC).  */
     5376        if (fTeleporterEnabled)
     5377        {
     5378            rc = mMachine->COMSETTER(TeleporterEnabled)(FALSE);
     5379            if (FAILED(rc))
     5380                throw rc;
     5381        }
     5382#endif
     5383
     5384        /* test the FaultToleranceState property  */
     5385        FaultToleranceState_T enmFaultToleranceState;
     5386        rc = mMachine->COMGETTER(FaultToleranceState)(&enmFaultToleranceState);
     5387        if (FAILED(rc))
     5388            throw rc;
     5389        BOOL fFaultToleranceSyncEnabled = (enmFaultToleranceState == FaultToleranceState_Standby);
     5390
     5391        /* Create a progress object to track progress of this operation. Must
     5392         * be done as early as possible (together with BeginPowerUp()) as this
     5393         * is vital for communicating as much as possible early powerup
     5394         * failure information to the API caller */
     5395        pPowerupProgress.createObject();
     5396        Bstr progressDesc;
     5397        if (mMachineState == MachineState_Saved)
     5398            progressDesc = tr("Restoring virtual machine");
     5399        else if (fTeleporterEnabled)
     5400            progressDesc = tr("Teleporting virtual machine");
     5401        else if (fFaultToleranceSyncEnabled)
     5402            progressDesc = tr("Fault Tolerance syncing of remote virtual machine");
     5403        else
     5404            progressDesc = tr("Starting virtual machine");
     5405        if (    mMachineState == MachineState_Saved
     5406            ||  (!fTeleporterEnabled && !fFaultToleranceSyncEnabled))
     5407            rc = pPowerupProgress->init(static_cast<IConsole *>(this),
     5408                                        progressDesc.raw(),
     5409                                        FALSE /* aCancelable */);
     5410        else
     5411        if (fTeleporterEnabled)
     5412            rc = pPowerupProgress->init(static_cast<IConsole *>(this),
     5413                                        progressDesc.raw(),
     5414                                        TRUE /* aCancelable */,
     5415                                        3    /* cOperations */,
     5416                                        10   /* ulTotalOperationsWeight */,
     5417                                        Bstr(tr("Teleporting virtual machine")).raw(),
     5418                                        1    /* ulFirstOperationWeight */,
     5419                                        NULL);
     5420        else
     5421        if (fFaultToleranceSyncEnabled)
     5422            rc = pPowerupProgress->init(static_cast<IConsole *>(this),
     5423                                        progressDesc.raw(),
     5424                                        TRUE /* aCancelable */,
     5425                                        3    /* cOperations */,
     5426                                        10   /* ulTotalOperationsWeight */,
     5427                                        Bstr(tr("Fault Tolerance syncing of remote virtual machine")).raw(),
     5428                                        1    /* ulFirstOperationWeight */,
     5429                                        NULL);
     5430
     5431        if (FAILED(rc))
     5432            throw rc;
     5433
     5434        /* Tell VBoxSVC and Machine about the progress object so they can
     5435           combine/proxy it to any openRemoteSession caller. */
     5436        LogFlowThisFunc(("Calling BeginPowerUp...\n"));
     5437        rc = mControl->BeginPowerUp(pPowerupProgress);
     5438        if (FAILED(rc))
     5439        {
     5440            LogFlowThisFunc(("BeginPowerUp failed\n"));
     5441            throw rc;
     5442        }
     5443        fBeganPoweringUp = true;
     5444
     5445        /** @todo this code prevents starting a VM with unavailable bridged
     5446         * networking interface. The only benefit is a slightly better error
     5447         * message, which should be moved to the driver code. This is the
     5448         * only reason why I left the code in for now. The driver allows
     5449         * unavailable bridged networking interfaces in certain circumstances,
     5450         * and this is sabotaged by this check. The VM will initially have no
     5451         * network connectivity, but the user can fix this at runtime. */
     5452#if 0
     5453        /* the network cards will undergo a quick consistency check */
     5454        for (ULONG slot = 0;
     5455             slot < SchemaDefs::NetworkAdapterCount;
     5456             ++slot)
     5457        {
     5458            ComPtr<INetworkAdapter> pNetworkAdapter;
     5459            mMachine->GetNetworkAdapter(slot, pNetworkAdapter.asOutParam());
     5460            BOOL enabled = FALSE;
     5461            pNetworkAdapter->COMGETTER(Enabled)(&enabled);
     5462            if (!enabled)
     5463                continue;
     5464
     5465            NetworkAttachmentType_T netattach;
     5466            pNetworkAdapter->COMGETTER(AttachmentType)(&netattach);
     5467            switch (netattach)
    53835468            {
    5384 #ifdef RT_OS_WINDOWS
    5385                 /* a valid host interface must have been set */
    5386                 Bstr hostif;
    5387                 pNetworkAdapter->COMGETTER(HostInterface)(hostif.asOutParam());
    5388                 if (hostif.isEmpty())
     5469                case NetworkAttachmentType_Bridged:
    53895470                {
    5390                     return setError(VBOX_E_HOST_ERROR,
    5391                         tr("VM cannot start because host interface networking requires a host interface name to be set"));
     5471                    /* a valid host interface must have been set */
     5472                    Bstr hostif;
     5473                    pNetworkAdapter->COMGETTER(HostInterface)(hostif.asOutParam());
     5474                    if (hostif.isEmpty())
     5475                    {
     5476                        throw setError(VBOX_E_HOST_ERROR,
     5477                            tr("VM cannot start because host interface networking requires a host interface name to be set"));
     5478                    }
     5479                    ComPtr<IVirtualBox> pVirtualBox;
     5480                    mMachine->COMGETTER(Parent)(pVirtualBox.asOutParam());
     5481                    ComPtr<IHost> pHost;
     5482                    pVirtualBox->COMGETTER(Host)(pHost.asOutParam());
     5483                    ComPtr<IHostNetworkInterface> pHostInterface;
     5484                    if (!SUCCEEDED(pHost->FindHostNetworkInterfaceByName(hostif.raw(),
     5485                                                                         pHostInterface.asOutParam())))
     5486                    {
     5487                        throw setError(VBOX_E_HOST_ERROR,
     5488                            tr("VM cannot start because the host interface '%ls' does not exist"),
     5489                            hostif.raw());
     5490                    }
     5491                    break;
    53925492                }
    5393                 ComPtr<IVirtualBox> pVirtualBox;
    5394                 mMachine->COMGETTER(Parent)(pVirtualBox.asOutParam());
    5395                 ComPtr<IHost> pHost;
    5396                 pVirtualBox->COMGETTER(Host)(pHost.asOutParam());
    5397                 ComPtr<IHostNetworkInterface> pHostInterface;
    5398                 if (!SUCCEEDED(pHost->FindHostNetworkInterfaceByName(hostif.raw(),
    5399                                                                      pHostInterface.asOutParam())))
     5493                default:
     5494                    break;
     5495            }
     5496        }
     5497#endif // 0
     5498
     5499        /* Read console data stored in the saved state file (if not yet done) */
     5500        rc = loadDataFromSavedState();
     5501        if (FAILED(rc))
     5502            throw rc;
     5503
     5504        /* Check all types of shared folders and compose a single list */
     5505        SharedFolderDataMap sharedFolders;
     5506        {
     5507            /* first, insert global folders */
     5508            for (SharedFolderDataMap::const_iterator it = mGlobalSharedFolders.begin();
     5509                 it != mGlobalSharedFolders.end(); ++ it)
     5510                sharedFolders[it->first] = it->second;
     5511
     5512            /* second, insert machine folders */
     5513            for (SharedFolderDataMap::const_iterator it = mMachineSharedFolders.begin();
     5514                 it != mMachineSharedFolders.end(); ++ it)
     5515                sharedFolders[it->first] = it->second;
     5516
     5517            /* third, insert console folders */
     5518            for (SharedFolderMap::const_iterator it = mSharedFolders.begin();
     5519                 it != mSharedFolders.end(); ++ it)
     5520                sharedFolders[it->first] = SharedFolderData(it->second->getHostPath(),
     5521                                                            it->second->isWritable(),
     5522                                                            it->second->isAutoMounted());
     5523        }
     5524
     5525        Bstr savedStateFile;
     5526
     5527        /*
     5528         * Saved VMs will have to prove that their saved states seem kosher.
     5529         */
     5530        if (mMachineState == MachineState_Saved)
     5531        {
     5532            rc = mMachine->COMGETTER(StateFilePath)(savedStateFile.asOutParam());
     5533            if (FAILED(rc))
     5534                throw rc;
     5535            ComAssertRet(!savedStateFile.isEmpty(), E_FAIL);
     5536            int vrc = SSMR3ValidateFile(Utf8Str(savedStateFile).c_str(), false /* fChecksumIt */);
     5537            if (RT_FAILURE(vrc))
     5538                throw setError(VBOX_E_FILE_ERROR,
     5539                                tr("VM cannot start because the saved state file '%ls' is invalid (%Rrc). Delete the saved state prior to starting the VM"),
     5540                                savedStateFile.raw(), vrc);
     5541        }
     5542
     5543        LogFlowThisFunc(("Checking if canceled...\n"));
     5544        BOOL fCanceled;
     5545        rc = pPowerupProgress->COMGETTER(Canceled)(&fCanceled);
     5546        if (FAILED(rc))
     5547            throw rc;
     5548        if (fCanceled)
     5549        {
     5550            LogFlowThisFunc(("Canceled in BeginPowerUp\n"));
     5551            throw setError(E_FAIL, tr("Powerup was canceled"));
     5552        }
     5553        LogFlowThisFunc(("Not canceled yet.\n"));
     5554
     5555        /* setup task object and thread to carry out the operation
     5556         * asynchronously */
     5557
     5558        std::auto_ptr<VMPowerUpTask> task(new VMPowerUpTask(this, pPowerupProgress));
     5559        ComAssertComRCRetRC(task->rc());
     5560
     5561        task->mConfigConstructor = configConstructor;
     5562        task->mSharedFolders = sharedFolders;
     5563        task->mStartPaused = aPaused;
     5564        if (mMachineState == MachineState_Saved)
     5565            task->mSavedStateFile = savedStateFile;
     5566        task->mTeleporterEnabled = fTeleporterEnabled;
     5567        task->mEnmFaultToleranceState = enmFaultToleranceState;
     5568
     5569        /* Reset differencing hard disks for which autoReset is true,
     5570         * but only if the machine has no snapshots OR the current snapshot
     5571         * is an OFFLINE snapshot; otherwise we would reset the current
     5572         * differencing image of an ONLINE snapshot which contains the disk
     5573         * state of the machine while it was previously running, but without
     5574         * the corresponding machine state, which is equivalent to powering
     5575         * off a running machine and not good idea
     5576         */
     5577        ComPtr<ISnapshot> pCurrentSnapshot;
     5578        rc = mMachine->COMGETTER(CurrentSnapshot)(pCurrentSnapshot.asOutParam());
     5579        if (FAILED(rc))
     5580            throw rc;
     5581
     5582        BOOL fCurrentSnapshotIsOnline = false;
     5583        if (pCurrentSnapshot)
     5584        {
     5585            rc = pCurrentSnapshot->COMGETTER(Online)(&fCurrentSnapshotIsOnline);
     5586            if (FAILED(rc))
     5587                throw rc;
     5588        }
     5589
     5590        if (!fCurrentSnapshotIsOnline)
     5591        {
     5592            LogFlowThisFunc(("Looking for immutable images to reset\n"));
     5593
     5594            com::SafeIfaceArray<IMediumAttachment> atts;
     5595            rc = mMachine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(atts));
     5596            if (FAILED(rc))
     5597                throw rc;
     5598
     5599            for (size_t i = 0;
     5600                 i < atts.size();
     5601                 ++i)
     5602            {
     5603                DeviceType_T devType;
     5604                rc = atts[i]->COMGETTER(Type)(&devType);
     5605                /** @todo later applies to floppies as well */
     5606                if (devType == DeviceType_HardDisk)
    54005607                {
    5401                     return setError(VBOX_E_HOST_ERROR,
    5402                         tr("VM cannot start because the host interface '%ls' does not exist"),
    5403                         hostif.raw());
    5404                 }
    5405 #endif /* RT_OS_WINDOWS */
    5406                 break;
    5407             }
    5408             default:
    5409                 break;
    5410         }
    5411     }
    5412 
    5413     /* Read console data stored in the saved state file (if not yet done) */
    5414     rc = loadDataFromSavedState();
    5415     if (FAILED(rc)) return rc;
    5416 
    5417     /* Check all types of shared folders and compose a single list */
    5418     SharedFolderDataMap sharedFolders;
    5419     {
    5420         /* first, insert global folders */
    5421         for (SharedFolderDataMap::const_iterator it = mGlobalSharedFolders.begin();
    5422              it != mGlobalSharedFolders.end(); ++ it)
    5423             sharedFolders[it->first] = it->second;
    5424 
    5425         /* second, insert machine folders */
    5426         for (SharedFolderDataMap::const_iterator it = mMachineSharedFolders.begin();
    5427              it != mMachineSharedFolders.end(); ++ it)
    5428             sharedFolders[it->first] = it->second;
    5429 
    5430         /* third, insert console folders */
    5431         for (SharedFolderMap::const_iterator it = mSharedFolders.begin();
    5432              it != mSharedFolders.end(); ++ it)
    5433             sharedFolders[it->first] = SharedFolderData(it->second->getHostPath(),
    5434                                                         it->second->isWritable(),
    5435                                                         it->second->isAutoMounted());
    5436     }
    5437 
    5438     Bstr savedStateFile;
    5439 
    5440     /*
    5441      * Saved VMs will have to prove that their saved states seem kosher.
    5442      */
    5443     if (mMachineState == MachineState_Saved)
    5444     {
    5445         rc = mMachine->COMGETTER(StateFilePath)(savedStateFile.asOutParam());
    5446         if (FAILED(rc)) return rc;
    5447         ComAssertRet(!savedStateFile.isEmpty(), E_FAIL);
    5448         int vrc = SSMR3ValidateFile(Utf8Str(savedStateFile).c_str(), false /* fChecksumIt */);
    5449         if (RT_FAILURE(vrc))
    5450             return setError(VBOX_E_FILE_ERROR,
    5451                             tr("VM cannot start because the saved state file '%ls' is invalid (%Rrc). Delete the saved state prior to starting the VM"),
    5452                             savedStateFile.raw(), vrc);
    5453     }
    5454 
    5455     /* test and clear the TeleporterEnabled property  */
    5456     BOOL fTeleporterEnabled;
    5457     rc = mMachine->COMGETTER(TeleporterEnabled)(&fTeleporterEnabled);
    5458     if (FAILED(rc)) return rc;
    5459 #if 0 /** @todo we should save it afterwards, but that isn't necessarily a good idea. Find a better place for this (VBoxSVC).  */
    5460     if (fTeleporterEnabled)
    5461     {
    5462         rc = mMachine->COMSETTER(TeleporterEnabled)(FALSE);
    5463         if (FAILED(rc)) return rc;
    5464     }
    5465 #endif
    5466 
    5467     /* test the FaultToleranceState property  */
    5468     FaultToleranceState_T enmFaultToleranceState;
    5469     rc = mMachine->COMGETTER(FaultToleranceState)(&enmFaultToleranceState);
    5470     if (FAILED(rc)) return rc;
    5471     BOOL fFaultToleranceSyncEnabled = (enmFaultToleranceState == FaultToleranceState_Standby);
    5472 
    5473     /* create a progress object to track progress of this operation */
    5474     ComObjPtr<Progress> pPowerupProgress;
    5475     pPowerupProgress.createObject();
    5476     Bstr progressDesc;
    5477     if (mMachineState == MachineState_Saved)
    5478         progressDesc = tr("Restoring virtual machine");
    5479     else if (fTeleporterEnabled)
    5480         progressDesc = tr("Teleporting virtual machine");
    5481     else if (fFaultToleranceSyncEnabled)
    5482         progressDesc = tr("Fault Tolerance syncing of remote virtual machine");
    5483     else
    5484         progressDesc = tr("Starting virtual machine");
    5485     if (    mMachineState == MachineState_Saved
    5486         ||  (!fTeleporterEnabled && !fFaultToleranceSyncEnabled))
    5487         rc = pPowerupProgress->init(static_cast<IConsole *>(this),
    5488                                     progressDesc.raw(),
    5489                                     FALSE /* aCancelable */);
    5490     else
    5491     if (fTeleporterEnabled)
    5492         rc = pPowerupProgress->init(static_cast<IConsole *>(this),
    5493                                     progressDesc.raw(),
    5494                                     TRUE /* aCancelable */,
    5495                                     3    /* cOperations */,
    5496                                     10   /* ulTotalOperationsWeight */,
    5497                                     Bstr(tr("Teleporting virtual machine")).raw(),
    5498                                     1    /* ulFirstOperationWeight */,
    5499                                     NULL);
    5500     else
    5501     if (fFaultToleranceSyncEnabled)
    5502         rc = pPowerupProgress->init(static_cast<IConsole *>(this),
    5503                                     progressDesc.raw(),
    5504                                     TRUE /* aCancelable */,
    5505                                     3    /* cOperations */,
    5506                                     10   /* ulTotalOperationsWeight */,
    5507                                     Bstr(tr("Fault Tolerance syncing of remote virtual machine")).raw(),
    5508                                     1    /* ulFirstOperationWeight */,
    5509                                     NULL);
    5510 
    5511     if (FAILED(rc))
    5512         return rc;
    5513 
    5514     /* Tell VBoxSVC and Machine about the progress object so they can combine
    5515        proxy it to any openRemoteSession caller. */
    5516     LogFlowThisFunc(("Calling BeginPowerUp...\n"));
    5517     rc = mControl->BeginPowerUp(pPowerupProgress);
    5518     if (FAILED(rc))
    5519     {
    5520         LogFlowThisFunc(("BeginPowerUp failed\n"));
    5521         return rc;
    5522     }
    5523 
    5524     LogFlowThisFunc(("Checking if canceled...\n"));
    5525     BOOL fCanceled;
    5526     rc = pPowerupProgress->COMGETTER(Canceled)(&fCanceled);
    5527     if (FAILED(rc))
    5528         return rc;
    5529     if (fCanceled)
    5530     {
    5531         LogFlowThisFunc(("Canceled in BeginPowerUp\n"));
    5532         return setError(E_FAIL, tr("Powerup was canceled"));
    5533     }
    5534     LogFlowThisFunc(("Not canceled yet.\n"));
    5535 
    5536     /* setup task object and thread to carry out the operation
    5537      * asynchronously */
    5538 
    5539     std::auto_ptr<VMPowerUpTask> task(new VMPowerUpTask(this, pPowerupProgress));
    5540     ComAssertComRCRetRC(task->rc());
    5541 
    5542     task->mConfigConstructor = configConstructor;
    5543     task->mSharedFolders = sharedFolders;
    5544     task->mStartPaused = aPaused;
    5545     if (mMachineState == MachineState_Saved)
    5546         task->mSavedStateFile = savedStateFile;
    5547     task->mTeleporterEnabled = fTeleporterEnabled;
    5548     task->mEnmFaultToleranceState = enmFaultToleranceState;
    5549 
    5550     /* Reset differencing hard disks for which autoReset is true,
    5551      * but only if the machine has no snapshots OR the current snapshot
    5552      * is an OFFLINE snapshot; otherwise we would reset the current differencing
    5553      * image of an ONLINE snapshot which contains the disk state of the machine
    5554      * while it was previously running, but without the corresponding machine
    5555      * state, which is equivalent to powering off a running machine and not
    5556      * good idea
    5557      */
    5558     ComPtr<ISnapshot> pCurrentSnapshot;
    5559     rc = mMachine->COMGETTER(CurrentSnapshot)(pCurrentSnapshot.asOutParam());
    5560     if (FAILED(rc)) return rc;
    5561 
    5562     BOOL fCurrentSnapshotIsOnline = false;
    5563     if (pCurrentSnapshot)
    5564     {
    5565         rc = pCurrentSnapshot->COMGETTER(Online)(&fCurrentSnapshotIsOnline);
    5566         if (FAILED(rc)) return rc;
    5567     }
    5568 
    5569     if (!fCurrentSnapshotIsOnline)
    5570     {
    5571         LogFlowThisFunc(("Looking for immutable images to reset\n"));
    5572 
    5573         com::SafeIfaceArray<IMediumAttachment> atts;
    5574         rc = mMachine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(atts));
    5575         if (FAILED(rc)) return rc;
    5576 
    5577         for (size_t i = 0;
    5578              i < atts.size();
    5579              ++i)
    5580         {
    5581             DeviceType_T devType;
    5582             rc = atts[i]->COMGETTER(Type)(&devType);
    5583             /** @todo later applies to floppies as well */
    5584             if (devType == DeviceType_HardDisk)
    5585             {
    5586                 ComPtr<IMedium> pMedium;
    5587                 rc = atts[i]->COMGETTER(Medium)(pMedium.asOutParam());
    5588                 if (FAILED(rc)) return rc;
    5589 
    5590                 /* needs autoreset? */
    5591                 BOOL autoReset = FALSE;
    5592                 rc = pMedium->COMGETTER(AutoReset)(&autoReset);
    5593                 if (FAILED(rc)) return rc;
    5594 
    5595                 if (autoReset)
    5596                 {
    5597                     ComPtr<IProgress> pResetProgress;
    5598                     rc = pMedium->Reset(pResetProgress.asOutParam());
    5599                     if (FAILED(rc)) return rc;
    5600 
    5601                     /* save for later use on the powerup thread */
    5602                     task->hardDiskProgresses.push_back(pResetProgress);
     5608                    ComPtr<IMedium> pMedium;
     5609                    rc = atts[i]->COMGETTER(Medium)(pMedium.asOutParam());
     5610                    if (FAILED(rc))
     5611                        throw rc;
     5612
     5613                    /* needs autoreset? */
     5614                    BOOL autoReset = FALSE;
     5615                    rc = pMedium->COMGETTER(AutoReset)(&autoReset);
     5616                    if (FAILED(rc))
     5617                        throw rc;
     5618
     5619                    if (autoReset)
     5620                    {
     5621                        ComPtr<IProgress> pResetProgress;
     5622                        rc = pMedium->Reset(pResetProgress.asOutParam());
     5623                        if (FAILED(rc))
     5624                            throw rc;
     5625
     5626                        /* save for later use on the powerup thread */
     5627                        task->hardDiskProgresses.push_back(pResetProgress);
     5628                    }
    56035629                }
    56045630            }
    56055631        }
    5606     }
    5607     else
    5608         LogFlowThisFunc(("Machine has a current snapshot which is online, skipping immutable images reset\n"));
    5609 
    5610     rc = consoleInitReleaseLog(mMachine);
    5611     if (FAILED(rc)) return rc;
     5632        else
     5633            LogFlowThisFunc(("Machine has a current snapshot which is online, skipping immutable images reset\n"));
     5634
     5635        rc = consoleInitReleaseLog(mMachine);
     5636        if (FAILED(rc))
     5637            throw rc;
    56125638
    56135639#ifdef RT_OS_SOLARIS
    5614     /* setup host core dumper for the VM */
    5615     Bstr value;
    5616     HRESULT hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpEnabled").raw(), value.asOutParam());
    5617     if (SUCCEEDED(hrc) && value == "1")
    5618     {
    5619         Bstr coreDumpDir, coreDumpReplaceSys, coreDumpLive;
    5620         mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpDir").raw(), coreDumpDir.asOutParam());
    5621         mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpReplaceSystemDump").raw(), coreDumpReplaceSys.asOutParam());
    5622         mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpLive").raw(), coreDumpLive.asOutParam());
    5623 
    5624         uint32_t fCoreFlags = 0;
    5625         if (   coreDumpReplaceSys.isEmpty() == false
    5626             && Utf8Str(coreDumpReplaceSys).toUInt32() == 1)
    5627         {
    5628             fCoreFlags |= RTCOREDUMPER_FLAGS_REPLACE_SYSTEM_DUMP;
    5629         }
    5630 
    5631         if (   coreDumpLive.isEmpty() == false
    5632             && Utf8Str(coreDumpLive).toUInt32() == 1)
    5633         {
    5634             fCoreFlags |= RTCOREDUMPER_FLAGS_LIVE_CORE;
    5635         }
    5636 
    5637         Utf8Str strDumpDir(coreDumpDir);
    5638         const char *pszDumpDir = strDumpDir.c_str();
    5639         if (   pszDumpDir
    5640             && *pszDumpDir == '\0')
    5641             pszDumpDir = NULL;
    5642 
    5643         int vrc;
    5644         if (   pszDumpDir
    5645             && !RTDirExists(pszDumpDir))
    5646         {
    5647             /*
    5648              * Try create the directory.
    5649              */
    5650             vrc = RTDirCreateFullPath(pszDumpDir, 0777);
     5640        /* setup host core dumper for the VM */
     5641        Bstr value;
     5642        HRESULT hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpEnabled").raw(), value.asOutParam());
     5643        if (SUCCEEDED(hrc) && value == "1")
     5644        {
     5645            Bstr coreDumpDir, coreDumpReplaceSys, coreDumpLive;
     5646            mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpDir").raw(), coreDumpDir.asOutParam());
     5647            mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpReplaceSystemDump").raw(), coreDumpReplaceSys.asOutParam());
     5648            mMachine->GetExtraData(Bstr("VBoxInternal2/CoreDumpLive").raw(), coreDumpLive.asOutParam());
     5649
     5650            uint32_t fCoreFlags = 0;
     5651            if (   coreDumpReplaceSys.isEmpty() == false
     5652                && Utf8Str(coreDumpReplaceSys).toUInt32() == 1)
     5653            {
     5654                fCoreFlags |= RTCOREDUMPER_FLAGS_REPLACE_SYSTEM_DUMP;
     5655            }
     5656
     5657            if (   coreDumpLive.isEmpty() == false
     5658                && Utf8Str(coreDumpLive).toUInt32() == 1)
     5659            {
     5660                fCoreFlags |= RTCOREDUMPER_FLAGS_LIVE_CORE;
     5661            }
     5662
     5663            Utf8Str strDumpDir(coreDumpDir);
     5664            const char *pszDumpDir = strDumpDir.c_str();
     5665            if (   pszDumpDir
     5666                && *pszDumpDir == '\0')
     5667                pszDumpDir = NULL;
     5668
     5669            int vrc;
     5670            if (   pszDumpDir
     5671                && !RTDirExists(pszDumpDir))
     5672            {
     5673                /*
     5674                 * Try create the directory.
     5675                 */
     5676                vrc = RTDirCreateFullPath(pszDumpDir, 0777);
     5677                if (RT_FAILURE(vrc))
     5678                    throw setError(E_FAIL, "Failed to setup CoreDumper. Couldn't create dump directory '%s' (%Rrc)\n", pszDumpDir, vrc);
     5679            }
     5680
     5681            vrc = RTCoreDumperSetup(pszDumpDir, fCoreFlags);
    56515682            if (RT_FAILURE(vrc))
    5652                 return setError(E_FAIL, "Failed to setup CoreDumper. Couldn't create dump directory '%s' (%Rrc)\n", pszDumpDir, vrc);
    5653         }
    5654 
    5655         vrc = RTCoreDumperSetup(pszDumpDir, fCoreFlags);
     5683                throw setError(E_FAIL, "Failed to setup CoreDumper (%Rrc)", vrc);
     5684            else
     5685                LogRel(("CoreDumper setup successful. pszDumpDir=%s fFlags=%#x\n", pszDumpDir ? pszDumpDir : ".", fCoreFlags));
     5686        }
     5687#endif
     5688
     5689        /* pass the progress object to the caller if requested */
     5690        if (aProgress)
     5691        {
     5692            if (task->hardDiskProgresses.size() == 0)
     5693            {
     5694                /* there are no other operations to track, return the powerup
     5695                 * progress only */
     5696                pPowerupProgress.queryInterfaceTo(aProgress);
     5697            }
     5698            else
     5699            {
     5700                /* create a combined progress object */
     5701                ComObjPtr<CombinedProgress> pProgress;
     5702                pProgress.createObject();
     5703                VMPowerUpTask::ProgressList progresses(task->hardDiskProgresses);
     5704                progresses.push_back(ComPtr<IProgress> (pPowerupProgress));
     5705                rc = pProgress->init(static_cast<IConsole *>(this),
     5706                                     progressDesc.raw(), progresses.begin(),
     5707                                     progresses.end());
     5708                AssertComRCReturnRC(rc);
     5709                pProgress.queryInterfaceTo(aProgress);
     5710            }
     5711        }
     5712
     5713        int vrc = RTThreadCreate(NULL, Console::powerUpThread,
     5714                                 (void *)task.get(), 0,
     5715                                 RTTHREADTYPE_MAIN_WORKER, 0, "VMPowerUp");
    56565716        if (RT_FAILURE(vrc))
    5657             return setError(E_FAIL, "Failed to setup CoreDumper (%Rrc)", vrc);
     5717            throw setError(E_FAIL, "Could not create VMPowerUp thread (%Rrc)", vrc);
     5718
     5719        /* task is now owned by powerUpThread(), so release it */
     5720        task.release();
     5721
     5722        /* finally, set the state: no right to fail in this method afterwards
     5723         * since we've already started the thread and it is now responsible for
     5724         * any error reporting and appropriate state change! */
     5725        if (mMachineState == MachineState_Saved)
     5726            setMachineState(MachineState_Restoring);
     5727        else if (fTeleporterEnabled)
     5728            setMachineState(MachineState_TeleportingIn);
     5729        else if (enmFaultToleranceState == FaultToleranceState_Standby)
     5730            setMachineState(MachineState_FaultTolerantSyncing);
    56585731        else
    5659             LogRel(("CoreDumper setup successful. pszDumpDir=%s fFlags=%#x\n", pszDumpDir ? pszDumpDir : ".", fCoreFlags));
    5660     }
    5661 #endif
    5662 
    5663     /* pass the progress object to the caller if requested */
    5664     if (aProgress)
    5665     {
    5666         if (task->hardDiskProgresses.size() == 0)
    5667         {
    5668             /* there are no other operations to track, return the powerup
    5669              * progress only */
    5670             pPowerupProgress.queryInterfaceTo(aProgress);
    5671         }
    5672         else
    5673         {
    5674             /* create a combined progress object */
    5675             ComObjPtr<CombinedProgress> pProgress;
    5676             pProgress.createObject();
    5677             VMPowerUpTask::ProgressList progresses(task->hardDiskProgresses);
    5678             progresses.push_back(ComPtr<IProgress> (pPowerupProgress));
    5679             rc = pProgress->init(static_cast<IConsole *>(this),
    5680                                  progressDesc.raw(), progresses.begin(),
    5681                                  progresses.end());
    5682             AssertComRCReturnRC(rc);
    5683             pProgress.queryInterfaceTo(aProgress);
    5684         }
    5685     }
    5686 
    5687     int vrc = RTThreadCreate(NULL, Console::powerUpThread, (void *) task.get(),
    5688                              0, RTTHREADTYPE_MAIN_WORKER, 0, "VMPowerUp");
    5689     if (RT_FAILURE(vrc))
    5690         return setError(E_FAIL, "Could not create VMPowerUp thread (%Rrc)", vrc);
    5691 
    5692     /* task is now owned by powerUpThread(), so release it */
    5693     task.release();
    5694 
    5695     /* finally, set the state: no right to fail in this method afterwards
    5696      * since we've already started the thread and it is now responsible for
    5697      * any error reporting and appropriate state change! */
    5698 
    5699     if (mMachineState == MachineState_Saved)
    5700         setMachineState(MachineState_Restoring);
    5701     else if (fTeleporterEnabled)
    5702         setMachineState(MachineState_TeleportingIn);
    5703     else if (enmFaultToleranceState == FaultToleranceState_Standby)
    5704         setMachineState(MachineState_FaultTolerantSyncing);
    5705     else
    5706         setMachineState(MachineState_Starting);
    5707 
    5708     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
     5732            setMachineState(MachineState_Starting);
     5733    }
     5734    catch (HRESULT aRC) { rc = aRC; }
     5735
     5736    if (FAILED(rc) && fBeganPoweringUp)
     5737    {
     5738
     5739        /* The progress object will fetch the current error info */
     5740        if (!pPowerupProgress.isNull())
     5741            pPowerupProgress->notifyComplete(rc);
     5742
     5743        /* Save the error info across the IPC below. Can't be done before the
     5744         * progress notification above, as saving the error info deletes it
     5745         * from the current context, and thus the progress object wouldn't be
     5746         * updated correctly. */
     5747        ErrorInfoKeeper eik;
     5748
     5749        /* signal end of operation */
     5750        mControl->EndPowerUp(rc);
     5751    }
     5752
     5753    LogFlowThisFunc(("mMachineState=%d, rc=%Rhrc\n", mMachineState, rc));
    57095754    LogFlowThisFuncLeave();
    5710     return S_OK;
     5755    return rc;
    57115756}
    57125757
Note: See TracChangeset for help on using the changeset viewer.

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