Changeset 35563 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Jan 14, 2011 1:49:23 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 69447
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r35481 r35563 5357 5357 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 5358 5358 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 5364 5359 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) 5383 5468 { 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: 5389 5470 { 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; 5392 5492 } 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) 5400 5607 { 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 } 5603 5629 } 5604 5630 } 5605 5631 } 5606 }5607 else5608 LogFlowThisFunc(("Machine has a current snapshot which is online, skipping immutable images reset\n")); 5609 5610 rc = consoleInitReleaseLog(mMachine);5611 if (FAILED(rc)) returnrc;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; 5612 5638 5613 5639 #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); 5651 5682 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"); 5656 5716 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); 5658 5731 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)); 5709 5754 LogFlowThisFuncLeave(); 5710 return S_OK;5755 return rc; 5711 5756 } 5712 5757
Note:
See TracChangeset
for help on using the changeset viewer.