Changeset 55214 in vbox
- Timestamp:
- Apr 13, 2015 3:53:01 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 33 edited
-
doc/manual/en_US/SDKRef.xml (modified) (1 diff)
-
src/VBox/Frontends/VBoxAutostart/VBoxAutostartStop.cpp (modified) (2 diffs)
-
src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp (modified) (3 diffs)
-
src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp (modified) (4 diffs)
-
src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp (modified) (1 diff)
-
src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp (modified) (3 diffs)
-
src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp (modified) (2 diffs)
-
src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp (modified) (4 diffs)
-
src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp (modified) (4 diffs)
-
src/VBox/Frontends/VBoxShell/vboxshell.py (modified) (6 diffs)
-
src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendCOM.cpp (modified) (4 diffs)
-
src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp (modified) (5 diffs)
-
src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h (modified) (3 diffs)
-
src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp (modified) (1 diff)
-
src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp (modified) (3 diffs)
-
src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp (modified) (4 diffs)
-
src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp (modified) (5 diffs)
-
src/VBox/Frontends/VirtualBox/src/selector/VBoxSnapshotsWgt.cpp (modified) (6 diffs)
-
src/VBox/Frontends/VirtualBox/src/wizards/clonevm/UIWizardCloneVM.cpp (modified) (3 diffs)
-
src/VBox/Main/idl/VirtualBox.xidl (modified) (36 diffs)
-
src/VBox/Main/include/ConsoleImpl.h (modified) (8 diffs)
-
src/VBox/Main/include/Global.h (modified) (2 diffs)
-
src/VBox/Main/include/MachineImpl.h (modified) (13 diffs)
-
src/VBox/Main/include/SessionImpl.h (modified) (3 diffs)
-
src/VBox/Main/src-all/Global.cpp (modified) (3 diffs)
-
src/VBox/Main/src-client/ConsoleImpl.cpp (modified) (41 diffs)
-
src/VBox/Main/src-client/ConsoleImplTeleporter.cpp (modified) (2 diffs)
-
src/VBox/Main/src-client/SessionImpl.cpp (modified) (14 diffs)
-
src/VBox/Main/src-server/HostPower.cpp (modified) (3 diffs)
-
src/VBox/Main/src-server/MachineImpl.cpp (modified) (56 diffs)
-
src/VBox/Main/src-server/Performance.cpp (modified) (2 diffs)
-
src/VBox/Main/src-server/SnapshotImpl.cpp (modified) (54 diffs)
-
src/VBox/ValidationKit/testdriver/vboxwrappers.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/manual/en_US/SDKRef.xml
r55142 r55214 3856 3856 3857 3857 <itemizedlist> 3858 <listitem> 3859 <para>The methods for saving state, adopting a saved state file, 3860 discarding saved state, taking a snapshot, restoring 3861 a snapshot and deleting a snapshot have been moved from 3862 <computeroutput>IConsole</computeroutput> to 3863 <computeroutput>IMachine</computeroutput>. This straightens out the 3864 logical placement of methods and was necessary to resolve a 3865 long-standing issue, preventing 32 bit API clients from invokingi 3866 those operations in the case where no VM is running. 3867 Method 3868 <xref linkend="IMachine__saveState" 3869 xreflabel="IMachine::saveState()" /> replaces 3870 <computeroutput>IConsole::saveState()</computeroutput>, 3871 <xref linkend="IMachine__adoptSavedState" 3872 xreflabel="IMachine::adoptSavedState()" /> replaces 3873 <computeroutput>IConsole::adoptSavedState()</computeroutput>, 3874 <xref linkend="IMachine__discardSavedState" 3875 xreflabel="IMachine::discardSavedState()" /> replaces 3876 <computeroutput>IConsole::discardSavedState()</computeroutput>, 3877 <xref linkend="IMachine__takeSnapshot" 3878 xreflabel="IMachine::takeSnapshot()" /> replaces 3879 <computeroutput>IConsole::takeSnapshot()</computeroutput>, 3880 <xref linkend="IMachine__deleteSnapshot" 3881 xreflabel="IMachine::deleteSnapshot()" /> replaces 3882 <computeroutput>IConsole::deleteSnapshot()</computeroutput>, 3883 <xref linkend="IMachine__deleteSnapshotAndAllChildren" 3884 xreflabel="IMachine::deleteSnapshotAndAllChildren()" /> replaces 3885 <computeroutput>IConsole::deleteSnapshotAndAllChildren()</computeroutput>, 3886 <xref linkend="IMachine__deleteSnapshotRange" 3887 xreflabel="IMachine::deleteSnapshotRange()" /> replaces 3888 <computeroutput>IConsole::deleteSnapshotRange()</computeroutput> and 3889 <xref linkend="IMachine__restoreSnapshot" 3890 xreflabel="IMachine::restoreSnapshot()" /> replaces 3891 <computeroutput>IConsole::restoreSnapshot()</computeroutput>. 3892 Small adjustments to the parameter lists have been made to reduce 3893 the number of API calls when taking online snapshots etc.</para> 3894 </listitem> 3895 3896 <listitem> 3897 <para>Two new machine states have been introduced to allow proper 3898 distinction between saving state and taking a snapshot. 3899 <xref linkend="MachineState__Saving" xreflabel="MachineState_Saving" /> 3900 now is used exclusively while the VM's state is being saved, without 3901 any overlaps with snapshot functionality. The new state 3902 <xref linkend="MachineState__Snapshotting" xreflabel="MachineState_Snapshotting" /> 3903 is used when an offline snapshot is taken and likewise the new state 3904 <xref linkend="MachineState__OnlineSnapshotting" xreflabel="MachineState_OnlineSnapshotting" /> 3905 is used when an online snapshot is taken.</para> 3906 </listitem> 3907 3858 3908 <listitem> 3859 3909 <para>The method <xref linkend="IVirtualBox__createMedium" -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStop.cpp
r43967 r55214 51 51 { 52 52 HRESULT rc = S_OK; 53 ComPtr<IMachine> machine; 53 54 ComPtr<IProgress> progress; 54 55 … … 83 84 } 84 85 85 CHECK_ERROR(console, SaveState(progress.asOutParam())); 86 CHECK_ERROR(console, COMGETTER(Machine)(machine.asOutParam())); 87 CHECK_ERROR(machine, SaveState(progress.asOutParam())); 86 88 if (FAILED(rc)) 87 89 { -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp
r43967 r55214 48 48 case MachineState_Saved: 49 49 return "saved"; 50 case MachineState_Teleported: 51 return "teleported"; 50 52 case MachineState_Aborted: 51 53 return "aborted"; 52 case MachineState_Teleported:53 return "teleported";54 54 case MachineState_Running: 55 55 return "running"; … … 58 58 case MachineState_Stuck: 59 59 return fShort ? "gurumeditation" : "guru meditation"; 60 case MachineState_Teleporting: 61 return "teleporting"; 60 62 case MachineState_LiveSnapshotting: 61 63 return fShort ? "livesnapshotting" : "live snapshotting"; 62 case MachineState_Teleporting:63 return "teleporting";64 64 case MachineState_Starting: 65 65 return "starting"; … … 74 74 case MachineState_TeleportingIn: 75 75 return fShort ? "teleportingin" : "teleporting (incoming)"; 76 case MachineState_DeletingSnapshotOnline: 77 return fShort ? "deletingsnapshotlive" : "deleting snapshot live"; 78 case MachineState_DeletingSnapshotPaused: 79 return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused"; 80 case MachineState_OnlineSnapshotting: 81 return fShort ? "onlinesnapshotting" : "online snapshotting"; 76 82 case MachineState_RestoringSnapshot: 77 83 return fShort ? "restoringsnapshot" : "restoring snapshot"; 78 84 case MachineState_DeletingSnapshot: 79 85 return fShort ? "deletingsnapshot" : "deleting snapshot"; 80 case MachineState_DeletingSnapshotOnline:81 return fShort ? "deletingsnapshotlive" : "deleting snapshot live";82 case MachineState_DeletingSnapshotPaused:83 return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";84 86 case MachineState_SettingUp: 85 87 return fShort ? "settingup" : "setting up"; 88 case MachineState_Snapshotting: 89 return "snapshotting"; 86 90 default: 87 91 break; -
trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp
r43738 r55214 1 2 1 /* $Id$ */ 3 2 /** @file … … 6 5 7 6 /* 8 * Copyright (C) 2012 Oracle Corporation7 * Copyright (C) 2012-2015 Oracle Corporation 9 8 * 10 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 214 213 ComPtr<IConsole> console; 215 214 CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam())); 215 /* Get the associated session machine. */ 216 ComPtr<IMachine> sessionMachine; 217 CHECK_ERROR_BREAK(g_pSession, COMGETTER(Machine)(sessionMachine.asOutParam())); 216 218 217 219 ComPtr<IProgress> progress; … … 269 271 } 270 272 271 CHECK_ERROR( console, SaveState(progress.asOutParam()));273 CHECK_ERROR(sessionMachine, SaveState(progress.asOutParam())); 272 274 if (SUCCEEDED(rc)) 273 275 { -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
r55180 r55214 262 262 263 263 ComPtr<IProgress> progress; 264 CHECK_ERROR( console, SaveState(progress.asOutParam()));264 CHECK_ERROR(sessionMachine, SaveState(progress.asOutParam())); 265 265 if (FAILED(rc)) 266 266 { -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
r55180 r55214 139 139 case MachineState_Saved: 140 140 return "saved"; 141 case MachineState_Teleported: 142 return "teleported"; 141 143 case MachineState_Aborted: 142 144 return "aborted"; 143 case MachineState_Teleported:144 return "teleported";145 145 case MachineState_Running: 146 146 return "running"; … … 149 149 case MachineState_Stuck: 150 150 return fShort ? "gurumeditation" : "guru meditation"; 151 case MachineState_Teleporting: 152 return "teleporting"; 151 153 case MachineState_LiveSnapshotting: 152 154 return fShort ? "livesnapshotting" : "live snapshotting"; 153 case MachineState_Teleporting:154 return "teleporting";155 155 case MachineState_Starting: 156 156 return "starting"; … … 165 165 case MachineState_TeleportingIn: 166 166 return fShort ? "teleportingin" : "teleporting (incoming)"; 167 case MachineState_FaultTolerantSyncing: 168 return fShort ? "faulttolerantsyncing" : "fault tolerant syncing"; 169 case MachineState_DeletingSnapshotOnline: 170 return fShort ? "deletingsnapshotlive" : "deleting snapshot live"; 171 case MachineState_DeletingSnapshotPaused: 172 return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused"; 173 case MachineState_OnlineSnapshotting: 174 return fShort ? "onlinesnapshotting" : "online snapshotting"; 167 175 case MachineState_RestoringSnapshot: 168 176 return fShort ? "restoringsnapshot" : "restoring snapshot"; 169 177 case MachineState_DeletingSnapshot: 170 178 return fShort ? "deletingsnapshot" : "deleting snapshot"; 171 case MachineState_DeletingSnapshotOnline:172 return fShort ? "deletingsnapshotlive" : "deleting snapshot live";173 case MachineState_DeletingSnapshotPaused:174 return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";175 179 case MachineState_SettingUp: 176 return fShort ? "settingup" : "setting up"; 180 return fShort ? "settingup" : "setting up"; 181 case MachineState_Snapshotting: 182 return fShort ? "snapshotting" : "offline snapshotting"; 177 183 default: 178 184 break; -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp
r54791 r55214 650 650 do 651 651 { 652 ComPtr<I Console> console;653 CHECK_ERROR_BREAK(a->session, COMGETTER( Console)(console.asOutParam()));652 ComPtr<IMachine> console; 653 CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(machine.asOutParam())); 654 654 CHECK_ERROR_BREAK(console, DiscardSavedState(true /* fDeleteFile */)); 655 655 } while (0); … … 687 687 do 688 688 { 689 ComPtr<I Console> console;690 CHECK_ERROR_BREAK(a->session, COMGETTER( Console)(console.asOutParam()));691 CHECK_ERROR_BREAK( console, AdoptSavedState(Bstr(szStateFileAbs).raw()));689 ComPtr<IMachine> machine; 690 CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(machine.asOutParam())); 691 CHECK_ERROR_BREAK(machine, AdoptSavedState(Bstr(szStateFileAbs).raw())); 692 692 } while (0); 693 693 CHECK_ERROR_BREAK(a->session, UnlockMachine()); -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp
r53624 r55214 281 281 return 1; 282 282 283 /* we have to open a session for this task (new or shared) */ 284 CHECK_ERROR_RET(pMachine, LockMachine(a->session, LockType_Shared), 1); 283 285 do 284 286 { 285 /* we have to open a session for this task (new or shared) */ 286 rc = pMachine->LockMachine(a->session, LockType_Shared); 287 ComPtr<IConsole> pConsole; 288 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(pConsole.asOutParam())); 287 /* replace the (read-only) IMachine object by a writable one */ 288 CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(pMachine.asOutParam())); 289 289 290 290 /* switch based on the command */ … … 346 346 break; 347 347 348 if (fPause)349 {350 MachineState_T machineState;351 CHECK_ERROR_BREAK(pConsole, COMGETTER(State)(&machineState));352 if (machineState == MachineState_Running)353 CHECK_ERROR_BREAK(pConsole, Pause());354 else355 fPause = false;356 }357 358 348 ComPtr<IProgress> progress; 359 CHECK_ERROR_BREAK(pConsole, TakeSnapshot(name.raw(), desc.raw(), 349 CHECK_ERROR_BREAK(pMachine, TakeSnapshot(name.raw(), desc.raw(), 350 fPause, 360 351 progress.asOutParam())); 361 352 362 353 rc = showProgress(progress); 363 354 CHECK_PROGRESS_ERROR(progress, ("Failed to take snapshot")); 364 365 if (fPause)366 {367 MachineState_T machineState;368 CHECK_ERROR_BREAK(pConsole, COMGETTER(State)(&machineState));369 if (machineState == MachineState_Paused)370 {371 if (SUCCEEDED(rc))372 CHECK_ERROR_BREAK(pConsole, Resume());373 else374 pConsole->Resume();375 }376 }377 355 } 378 356 else if ( (fDelete = !strcmp(a->argv[1], "delete")) … … 417 395 if (fDelete) 418 396 { 419 CHECK_ERROR_BREAK(p Console, DeleteSnapshot(bstrSnapGuid.raw(),397 CHECK_ERROR_BREAK(pMachine, DeleteSnapshot(bstrSnapGuid.raw(), 420 398 pProgress.asOutParam())); 421 399 } … … 424 402 // restore or restore current 425 403 RTPrintf("Restoring snapshot %ls\n", bstrSnapGuid.raw()); 426 CHECK_ERROR_BREAK(p Console, RestoreSnapshot(pSnapshot, pProgress.asOutParam()));404 CHECK_ERROR_BREAK(pMachine, RestoreSnapshot(pSnapshot, pProgress.asOutParam())); 427 405 } 428 406 -
trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
r55133 r55214 1838 1838 if (machineState == MachineState_Saved) 1839 1839 { 1840 CHECK_ERROR(gp Console, DiscardSavedState(true /* fDeleteFile */));1840 CHECK_ERROR(gpMachine, DiscardSavedState(true /* fDeleteFile */)); 1841 1841 } 1842 1842 /* … … 1855 1855 goto leave; 1856 1856 1857 CHECK_ERROR(gp Console, RestoreSnapshot(pCurrentSnapshot, gpProgress.asOutParam()));1857 CHECK_ERROR(gpMachine, RestoreSnapshot(pCurrentSnapshot, gpProgress.asOutParam())); 1858 1858 rc = gpProgress->WaitForCompletion(-1); 1859 1859 } … … 4200 4200 UpdateTitlebar(TITLEBAR_SAVE); 4201 4201 gpProgress = NULL; 4202 HRESULT rc = gp Console->SaveState(gpProgress.asOutParam());4202 HRESULT rc = gpMachine->SaveState(gpProgress.asOutParam()); 4203 4203 if (FAILED(rc)) 4204 4204 { … … 4950 4950 gpProgress = NULL; 4951 4951 HRESULT rc; 4952 CHECK_ERROR(gp Console, TakeSnapshot(Bstr(pszSnapshotName).raw(),4952 CHECK_ERROR(gpMachine, TakeSnapshot(Bstr(pszSnapshotName).raw(), 4953 4953 Bstr("Taken by VBoxSDL").raw(), 4954 TRUE, 4954 4955 gpProgress.asOutParam())); 4955 4956 if (FAILED(rc)) -
trunk/src/VBox/Frontends/VBoxShell/vboxshell.py
r54434 r55214 250 250 print "removing machine ", mach.name, "with UUID", uuid 251 251 cmdClosedVm(ctx, mach, detachVmDevice, ["ALL"]) 252 mach= mach.unregister(ctx['global'].constants.CleanupMode_Full)252 disks = mach.unregister(ctx['global'].constants.CleanupMode_Full) 253 253 if mach: 254 mach.deleteSettings() 254 progress = mach.deleteConfig(disks) 255 if progressBar(ctx, progress, 100) and int(progress.resultCode) == 0: 256 print "Success!" 257 else: 258 reportError(ctx, progress) 255 259 # update cache 256 260 getMachines(ctx, True) … … 718 722 'ginfo': lambda: ginfo(ctx, console, args), 719 723 'guestlambda': lambda: args[0](ctx, mach, console, args[1:]), 720 'save': lambda: progressBar(ctx, console.saveState()),724 'save': lambda: progressBar(ctx, session.machine.saveState()), 721 725 'screenshot': lambda: takeScreenshot(ctx, console, args), 722 726 'teleport': lambda: teleport(ctx, session, console, args), … … 2631 2635 else: 2632 2636 desc = "" 2633 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.takeSnapshot(name, desc)))2637 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.takeSnapshot(name, desc, true))) 2634 2638 return 0 2635 2639 … … 2640 2644 name = args[3] 2641 2645 snap = mach.findSnapshot(name) 2642 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.restoreSnapshot(snap)))2646 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.restoreSnapshot(snap))) 2643 2647 return 0 2644 2648 … … 2648 2652 return 0 2649 2653 snap = mach.currentSnapshot() 2650 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.restoreSnapshot(snap)))2654 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.restoreSnapshot(snap))) 2651 2655 return 0 2652 2656 … … 2657 2661 name = args[3] 2658 2662 snap = mach.findSnapshot(name) 2659 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.deleteSnapshot(snap.id)))2663 cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.deleteSnapshot(snap.id))) 2660 2664 return 0 2661 2665 -
trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendCOM.cpp
r55140 r55214 5 5 6 6 /* 7 * Copyright (C) 2012-201 4Oracle Corporation7 * Copyright (C) 2012-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 73 73 case KMachineState_Stuck: return QColor(Qt::darkMagenta); 74 74 case KMachineState_Teleporting: return QColor(Qt::blue); 75 case KMachineState_Snapshotting: return QColor(Qt::green); 76 case KMachineState_OnlineSnapshotting: return QColor(Qt::green); 75 77 case KMachineState_LiveSnapshotting: return QColor(Qt::green); 76 78 case KMachineState_Starting: return QColor(Qt::green); … … 108 110 case KMachineState_Stuck: return UIIconPool::iconSet(":/state_stuck_16px.png"); 109 111 case KMachineState_Teleporting: return UIIconPool::iconSet(":/state_running_16px.png"); 112 case KMachineState_Snapshotting: return UIIconPool::iconSet(":/state_saving_16px.png"); 113 case KMachineState_OnlineSnapshotting: return UIIconPool::iconSet(":/state_running_16px.png"); 110 114 case KMachineState_LiveSnapshotting: return UIIconPool::iconSet(":/state_running_16px.png"); 111 115 case KMachineState_Starting: return UIIconPool::iconSet(":/state_running_16px.png"); … … 143 147 case KMachineState_Stuck: return QApplication::translate("VBoxGlobal", "Guru Meditation", "MachineState"); 144 148 case KMachineState_Teleporting: return QApplication::translate("VBoxGlobal", "Teleporting", "MachineState"); 149 case KMachineState_Snapshotting: return QApplication::translate("VBoxGlobal", "Taking Snapshot", "MachineState"); 150 case KMachineState_OnlineSnapshotting: return QApplication::translate("VBoxGlobal", "Taking Online Snapshot", "MachineState"); 145 151 case KMachineState_LiveSnapshotting: return QApplication::translate("VBoxGlobal", "Taking Live Snapshot", "MachineState"); 146 152 case KMachineState_Starting: return QApplication::translate("VBoxGlobal", "Starting", "MachineState"); -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp
r55115 r55214 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 766 766 } 767 767 768 void UIMessageCenter::cannotDiscardSavedState(const C Console &console) const768 void UIMessageCenter::cannotDiscardSavedState(const CMachine &machine) const 769 769 { 770 770 error(0, MessageType_Error, 771 771 tr("Failed to discard the saved state of the virtual machine <b>%1</b>.") 772 .arg( CConsole(console).GetMachine().GetName()),773 formatErrorInfo( console));774 } 775 776 void UIMessageCenter::cannotSaveMachineState(const C Console &console)772 .arg(machine.GetName()), 773 formatErrorInfo(machine)); 774 } 775 776 void UIMessageCenter::cannotSaveMachineState(const CMachine &machine) 777 777 { 778 778 error(0, MessageType_Error, 779 779 tr("Failed to save the state of the virtual machine <b>%1</b>.") 780 .arg( CConsole(console).GetMachine().GetName()),781 formatErrorInfo( console));780 .arg(machine.GetName()), 781 formatErrorInfo(machine)); 782 782 } 783 783 … … 866 866 } 867 867 868 void UIMessageCenter::cannotTakeSnapshot(const C Console &console, const QString &strMachineName, QWidget *pParent /* = 0*/) const868 void UIMessageCenter::cannotTakeSnapshot(const CMachine &machine, const QString &strMachineName, QWidget *pParent /* = 0*/) const 869 869 { 870 870 error(pParent, MessageType_Error, 871 871 tr("Failed to create a snapshot of the virtual machine <b>%1</b>.") 872 872 .arg(strMachineName), 873 formatErrorInfo( console));873 formatErrorInfo(machine)); 874 874 } 875 875 … … 882 882 } 883 883 884 bool UIMessageCenter::cannotRestoreSnapshot(const C Console &console, const QString &strSnapshotName, const QString &strMachineName) const884 bool UIMessageCenter::cannotRestoreSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const 885 885 { 886 886 error(0, MessageType_Error, 887 887 tr("Failed to restore the snapshot <b>%1</b> of the virtual machine <b>%2</b>.") 888 888 .arg(strSnapshotName, strMachineName), 889 formatErrorInfo( console));889 formatErrorInfo(machine)); 890 890 return false; 891 891 } … … 900 900 } 901 901 902 void UIMessageCenter::cannotRemoveSnapshot(const C Console &console, const QString &strSnapshotName, const QString &strMachineName) const902 void UIMessageCenter::cannotRemoveSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const 903 903 { 904 904 error(0, MessageType_Error, 905 905 tr("Failed to delete the snapshot <b>%1</b> of the virtual machine <b>%2</b>.") 906 906 .arg(strSnapshotName, strMachineName), 907 formatErrorInfo( console));907 formatErrorInfo(machine)); 908 908 } 909 909 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h
r54937 r55214 4 4 5 5 /* 6 * Copyright (C) 2006-201 3Oracle Corporation6 * Copyright (C) 2006-2014 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 191 191 void cannotPauseMachine(const CConsole &console) const; 192 192 void cannotResumeMachine(const CConsole &console) const; 193 void cannotDiscardSavedState(const C Console &console) const;194 void cannotSaveMachineState(const C Console &console);193 void cannotDiscardSavedState(const CMachine &machine) const; 194 void cannotSaveMachineState(const CMachine &machine); 195 195 void cannotSaveMachineState(const CProgress &progress, const QString &strMachineName); 196 196 void cannotACPIShutdownMachine(const CConsole &console) const; … … 203 203 bool warnAboutSnapshotRemovalFreeSpace(const QString &strSnapshotName, const QString &strTargetImageName, 204 204 const QString &strTargetImageMaxSize, const QString &strTargetFileSystemFree) const; 205 void cannotTakeSnapshot(const C Console &console, const QString &strMachineName, QWidget *pParent = 0) const;205 void cannotTakeSnapshot(const CMachine &machine, const QString &strMachineName, QWidget *pParent = 0) const; 206 206 void cannotTakeSnapshot(const CProgress &progress, const QString &strMachineName, QWidget *pParent = 0) const; 207 bool cannotRestoreSnapshot(const C Console &console, const QString &strSnapshotName, const QString &strMachineName) const;207 bool cannotRestoreSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const; 208 208 bool cannotRestoreSnapshot(const CProgress &progress, const QString &strSnapshotName, const QString &strMachineName) const; 209 void cannotRemoveSnapshot(const C Console &console, const QString &strSnapshotName, const QString &strMachineName) const;209 void cannotRemoveSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const; 210 210 void cannotRemoveSnapshot(const CProgress &progress, const QString &strSnapshotName, const QString &strMachineName) const; 211 211 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp
r53046 r55214 62 62 CSnapshot snapshot = machine.GetCurrentSnapshot(); 63 63 64 /* Open corresponding console: */65 CConsole console = session.GetConsole();66 64 /* Prepare restore-snapshot progress: */ 67 CProgress progress = console.RestoreSnapshot(snapshot);68 if (! console.isOk())69 return msgCenter().cannotRestoreSnapshot( console, snapshot.GetName(), machine.GetName());65 CProgress progress = machine.RestoreSnapshot(snapshot); 66 if (!machine.isOk()) 67 return msgCenter().cannotRestoreSnapshot(machine, snapshot.GetName(), machine.GetName()); 70 68 71 69 /* Show the snapshot-discarding progress: */ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
r55170 r55214 1391 1391 return; 1392 1392 1393 /* Remember the paused state: */1394 bool fWasPaused = uisession()->isPaused();1395 if (!fWasPaused)1396 {1397 /* Suspend the VM and ignore the close event if failed to do so.1398 * pause() will show the error message to the user. */1399 if (!uisession()->pause())1400 return;1401 }1402 1403 1393 /* Create take-snapshot dialog: */ 1404 1394 QWidget *pDlgParent = windowManager().realParentWindow(activeMachineWindow()); … … 1433 1423 { 1434 1424 /* Prepare the take-snapshot progress: */ 1435 CProgress progress = console().TakeSnapshot(strSnapshotName, strSnapshotDescription);1436 if ( console().isOk())1425 CProgress progress = machine().TakeSnapshot(strSnapshotName, strSnapshotDescription, true); 1426 if (machine().isOk()) 1437 1427 { 1438 1428 /* Show the take-snapshot progress: */ … … 1442 1432 } 1443 1433 else 1444 msgCenter().cannotTakeSnapshot(console(), machineName()); 1445 } 1446 1447 /* Restore the running state if needed: */ 1448 if (!fWasPaused) 1449 { 1450 /* Make sure machine-state-change callback is processed: */ 1451 QApplication::sendPostedEvents(uisession(), UIConsoleEventType_StateChange); 1452 /* Unpause VM: */ 1453 uisession()->unpause(); 1434 msgCenter().cannotTakeSnapshot(machine(), machineName()); 1454 1435 } 1455 1436 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
r55155 r55214 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 300 300 { 301 301 /* Prepare the saving progress: */ 302 CProgress progress = console().SaveState();303 if ( console().isOk())302 CProgress progress = machine().SaveState(); 303 if (machine().isOk()) 304 304 { 305 305 /* Show the saving progress: */ … … 315 315 { 316 316 /* Failed in console: */ 317 msgCenter().cannotSaveMachineState( console());317 msgCenter().cannotSaveMachineState(machine()); 318 318 return false; 319 319 } … … 408 408 do 409 409 { 410 /* Acquire console for this session: */411 C Console cons = sess.GetConsole();412 if ( cons.isNull())410 /* Acquire machine for this session: */ 411 CMachine machine = sess.GetMachine(); 412 if (machine.isNull()) 413 413 { 414 /* Unable to acquire console: */414 /* Unable to acquire machine: */ 415 415 break; 416 416 } 417 417 418 418 /* Prepare the snapshot-discard progress: */ 419 const CSnapshot snap = mach .GetCurrentSnapshot();420 CProgress prog = cons.RestoreSnapshot(snap);421 if (! cons.isOk() || prog.isNull())419 const CSnapshot snap = machine.GetCurrentSnapshot(); 420 CProgress prog = machine.RestoreSnapshot(snap); 421 if (!machine.isOk() || prog.isNull()) 422 422 { 423 423 /* Unable to restore snapshot: */ 424 msgCenter().cannotRestoreSnapshot( cons, snap.GetName(), machineName());424 msgCenter().cannotRestoreSnapshot(machine, snap.GetName(), machineName()); 425 425 break; 426 426 } 427 427 428 428 /* Show the snapshot-discard progress: */ 429 msgCenter().showModalProgressDialog(prog, mach .GetName(), ":/progress_snapshot_discard_90px.png");429 msgCenter().showModalProgressDialog(prog, machine.GetName(), ":/progress_snapshot_discard_90px.png"); 430 430 if (prog.GetResultCode() != 0) 431 431 { 432 432 /* Unable to restore snapshot: */ 433 msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), mach .GetName());433 msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), machine.GetName()); 434 434 break; 435 435 } -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp
r55170 r55214 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 498 498 return; 499 499 500 /* Get session console: */501 C Console console = session.GetConsole();502 console.DiscardSavedState(true);503 if (! console.isOk())504 msgCenter().cannotDiscardSavedState( console);500 /* Get session machine: */ 501 CMachine machine = session.GetMachine(); 502 machine.DiscardSavedState(true); 503 if (!machine.isOk()) 504 msgCenter().cannotDiscardSavedState(machine); 505 505 506 506 /* Unlock machine finally: */ … … 623 623 /* Get session console: */ 624 624 CConsole console = session.GetConsole(); 625 /* Get session machine: */ 626 CMachine machine = session.GetMachine(); 625 627 /* Pause VM first: */ 626 628 console.Pause(); … … 628 630 { 629 631 /* Prepare machine state saving: */ 630 CProgress progress = console.SaveState();631 if ( console.isOk())632 CProgress progress = machine.SaveState(); 633 if (machine.isOk()) 632 634 { 633 635 /* Show machine state saving progress: */ 634 CMachine machine = session.GetMachine();635 636 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_state_save_90px.png"); 636 637 if (!progress.isOk() || progress.GetResultCode() != 0) … … 638 639 } 639 640 else 640 msgCenter().cannotSaveMachineState( console);641 msgCenter().cannotSaveMachineState(machine); 641 642 } 642 643 else -
trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSnapshotsWgt.cpp
r54774 r55214 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 641 641 642 642 /* Restore chosen snapshot: */ 643 C Console console = session.GetConsole();644 CProgress progress = console.RestoreSnapshot(snapshot);645 if ( console.isOk())643 CMachine machine = session.GetMachine(); 644 CProgress progress = machine.RestoreSnapshot(snapshot); 645 if (machine.isOk()) 646 646 { 647 647 msgCenter().showModalProgressDialog(progress, mMachine.GetName(), ":/progress_snapshot_restore_90px.png"); … … 650 650 } 651 651 else 652 msgCenter().cannotRestoreSnapshot( console, snapshot.GetName(), mMachine.GetName());652 msgCenter().cannotRestoreSnapshot(machine, snapshot.GetName(), mMachine.GetName()); 653 653 654 654 /* Unlock machine finally: */ … … 688 688 return; 689 689 690 CConsole console = session.GetConsole(); 691 CProgress progress = console.DeleteSnapshot (snapId); 692 if (console.isOk()) 690 /* Remove chosen snapshot: */ 691 CMachine machine = session.GetMachine(); 692 CProgress progress = machine.DeleteSnapshot(snapId); 693 if (machine.isOk()) 693 694 { 694 695 /* Show the progress dialog */ … … 699 700 } 700 701 else 701 msgCenter().cannotRemoveSnapshot( console, snapshot.GetName(), mMachine.GetName());702 msgCenter().cannotRemoveSnapshot(machine, snapshot.GetName(), mMachine.GetName()); 702 703 703 704 session.UnlockMachine(); … … 829 830 if (fIsValid) 830 831 { 831 /* Get corresponding console object also: */ 832 CConsole console = session.GetConsole(); 833 /* Remember runtime state: */ 834 bool fAtRuntime = mMachine.GetState() == KMachineState_Running; 835 /* Remember paused state: */ 836 bool fWasPaused = mMachine.GetState() == KMachineState_Paused || 837 mMachine.GetState() == KMachineState_TeleportingPausedVM; 838 839 /* Pause VM if necessary: */ 840 if (fIsValid && fAtRuntime && !fWasPaused) 841 { 842 /* Pausing VM: */ 843 console.Pause(); 844 if (!console.isOk()) 832 /* Get corresponding machine object also: */ 833 CMachine machine = session.GetMachine(); 834 835 /* Create take-snapshot dialog: */ 836 QWidget *pDlgParent = windowManager().realParentWindow(this); 837 QPointer<VBoxTakeSnapshotDlg> pDlg = new VBoxTakeSnapshotDlg(pDlgParent, mMachine); 838 windowManager().registerNewParent(pDlg, pDlgParent); 839 840 /* Assign corresponding icon: */ 841 pDlg->mLbIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(mMachine.GetOSTypeId())); 842 843 /* Search for the max available snapshot index: */ 844 int iMaxSnapShotIndex = 0; 845 QString snapShotName = tr("Snapshot %1"); 846 QRegExp regExp(QString("^") + snapShotName.arg("([0-9]+)") + QString("$")); 847 QTreeWidgetItemIterator iterator(mTreeWidget); 848 while (*iterator) 849 { 850 QString snapShot = static_cast<SnapshotWgtItem*>(*iterator)->text(0); 851 int pos = regExp.indexIn(snapShot); 852 if (pos != -1) 853 iMaxSnapShotIndex = regExp.cap(1).toInt() > iMaxSnapShotIndex ? regExp.cap(1).toInt() : iMaxSnapShotIndex; 854 ++iterator; 855 } 856 pDlg->mLeName->setText(snapShotName.arg(iMaxSnapShotIndex + 1)); 857 858 /* Exec the dialog: */ 859 bool fDialogAccepted = pDlg->exec() == QDialog::Accepted; 860 861 /* Is the dialog still valid? */ 862 if (pDlg) 863 { 864 /* Acquire variables: */ 865 QString strSnapshotName = pDlg->mLeName->text().trimmed(); 866 QString strSnapshotDescription = pDlg->mTeDescription->toPlainText(); 867 868 /* Destroy dialog early: */ 869 delete pDlg; 870 871 /* Was the dialog accepted? */ 872 if (fDialogAccepted) 845 873 { 846 msgCenter().cannotPauseMachine(console); 847 fIsValid = false; 848 } 849 } 850 851 if (fIsValid) 852 { 853 /* Create take-snapshot dialog: */ 854 QWidget *pDlgParent = windowManager().realParentWindow(this); 855 QPointer<VBoxTakeSnapshotDlg> pDlg = new VBoxTakeSnapshotDlg(pDlgParent, mMachine); 856 windowManager().registerNewParent(pDlg, pDlgParent); 857 858 /* Assign corresponding icon: */ 859 pDlg->mLbIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(mMachine.GetOSTypeId())); 860 861 /* Search for the max available snapshot index: */ 862 int iMaxSnapShotIndex = 0; 863 QString snapShotName = tr("Snapshot %1"); 864 QRegExp regExp(QString("^") + snapShotName.arg("([0-9]+)") + QString("$")); 865 QTreeWidgetItemIterator iterator(mTreeWidget); 866 while (*iterator) 867 { 868 QString snapShot = static_cast<SnapshotWgtItem*>(*iterator)->text(0); 869 int pos = regExp.indexIn(snapShot); 870 if (pos != -1) 871 iMaxSnapShotIndex = regExp.cap(1).toInt() > iMaxSnapShotIndex ? regExp.cap(1).toInt() : iMaxSnapShotIndex; 872 ++iterator; 873 } 874 pDlg->mLeName->setText(snapShotName.arg(iMaxSnapShotIndex + 1)); 875 876 /* Exec the dialog: */ 877 bool fDialogAccepted = pDlg->exec() == QDialog::Accepted; 878 879 /* Is the dialog still valid? */ 880 if (pDlg) 881 { 882 /* Acquire variables: */ 883 QString strSnapshotName = pDlg->mLeName->text().trimmed(); 884 QString strSnapshotDescription = pDlg->mTeDescription->toPlainText(); 885 886 /* Destroy dialog early: */ 887 delete pDlg; 888 889 /* Was the dialog accepted? */ 890 if (fDialogAccepted) 874 /* Prepare the take-snapshot progress: */ 875 CProgress progress = machine.TakeSnapshot(strSnapshotName, strSnapshotDescription, true); 876 if (machine.isOk()) 891 877 { 892 /* Preparethe take-snapshot progress: */893 CProgress progress = console.TakeSnapshot(strSnapshotName, strSnapshotDescription);894 if ( console.isOk())878 /* Show the take-snapshot progress: */ 879 msgCenter().showModalProgressDialog(progress, mMachine.GetName(), ":/progress_snapshot_create_90px.png"); 880 if (!progress.isOk() || progress.GetResultCode() != 0) 895 881 { 896 /* Show the take-snapshot progress: */ 897 msgCenter().showModalProgressDialog(progress, mMachine.GetName(), ":/progress_snapshot_create_90px.png"); 898 if (!progress.isOk() || progress.GetResultCode() != 0) 899 { 900 msgCenter().cannotTakeSnapshot(progress, mMachine.GetName()); 901 fIsValid = false; 902 } 903 } 904 else 905 { 906 msgCenter().cannotTakeSnapshot(console, mMachine.GetName()); 882 msgCenter().cannotTakeSnapshot(progress, mMachine.GetName()); 907 883 fIsValid = false; 908 884 } 909 885 } 910 886 else 887 { 888 msgCenter().cannotTakeSnapshot(machine, mMachine.GetName()); 911 889 fIsValid = false; 890 } 912 891 } 913 892 else 914 893 fIsValid = false; 915 894 } 916 917 /* Resume VM if necessary: */ 918 if (fIsValid && fAtRuntime && !fWasPaused) 919 { 920 /* Resuming VM: */ 921 console.Resume(); 922 if (!console.isOk()) 923 { 924 msgCenter().cannotResumeMachine(console); 925 fIsValid = false; 926 } 927 } 895 else 896 fIsValid = false; 928 897 929 898 /* Unlock machine finally: */ -
trunk/src/VBox/Frontends/VirtualBox/src/wizards/clonevm/UIWizardCloneVM.cpp
r52730 r55214 5 5 6 6 /* 7 * Copyright (C) 2011-201 3Oracle Corporation7 * Copyright (C) 2011-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 79 79 return false; 80 80 81 /* Prepare console: */82 C Console console = session.GetConsole();81 /* Prepare machine: */ 82 CMachine machine = session.GetMachine(); 83 83 84 84 /* Take the snapshot: */ 85 85 QString strSnapshotName = tr("Linked Base for %1 and %2").arg(m_machine.GetName()).arg(strName); 86 CProgress progress = console.TakeSnapshot(strSnapshotName, "");87 88 if ( console.isOk())86 CProgress progress = machine.TakeSnapshot(strSnapshotName, "", true); 87 88 if (machine.isOk()) 89 89 { 90 90 /* Show the "Taking Snapshot" progress dialog: */ … … 99 99 else 100 100 { 101 msgCenter().cannotTakeSnapshot( console, m_machine.GetName(), this);101 msgCenter().cannotTakeSnapshot(machine, m_machine.GetName(), this); 102 102 return false; 103 103 } -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r55182 r55214 587 587 <enum 588 588 name="MachineState" 589 uuid=" ec6c6a9e-113d-4ff4-b44f-0b69f21c97fe"589 uuid="87f085c3-ca67-4e45-9225-6057f32e9e8e" 590 590 > 591 591 <desc> … … 597 597 Below is the basic virtual machine state diagram. It shows how the state 598 598 changes during virtual machine execution. The text in square braces shows 599 a method of the IConsole interface that performs the given state599 a method of the IConsole or IMachine interface that performs the given state 600 600 transition. 601 601 … … 611 611 | | +-----------------------------------------+-|-------------------+ + 612 612 | | | | | 613 | | +- - Saving <--------[takeSnapshot()]<-------+---------------------+613 | | +- OnlineSnapshotting <--[takeSnapshot()]<--+---------------------+ 614 614 | | | | 615 615 | +-------- Saving <--------[saveState()]<----------+---------------------+ … … 683 683 | | 684 684 +-> PoweredOff --+ | 685 | +-->[takeSnapshot()] ------------------ -> Saving ------+685 | +-->[takeSnapshot()] ------------------> Snapshotting -+ 686 686 +-> Aborted -----+ 687 687 … … 694 694 +---(Saved if restored from an online snapshot, PoweredOff otherwise)---+ 695 695 </pre> 696 697 Note that the Saving state is present in both the offline state group and698 online state group. Currently, the only way to determine what group is699 assumed in a particular case is to remember the previous machine state: if700 it was Running or Paused, then Saving is an online state, otherwise it is701 an offline state. This inconsistency may be removed in one of the future702 versions of VirtualBox by adding a new state.703 696 704 697 <note internal="yes"> … … 792 785 some of the runtime configuration options are inaccessible. Also, if 793 786 paused while in this state it will transition to 794 @c Saving and it will not be resume the787 @c OnlineSnapshotting and it will not be resume the 795 788 execution until the snapshot operation has completed. 796 789 </desc> … … 810 803 <const name="Saving" value="12"> 811 804 <desc> 812 Machine is saving its execution state to a file, or an online 813 snapshot of the machine is being taken. 805 Machine is saving its execution state to a file. 814 806 </desc> 815 807 </const> … … 824 816 The machine is being teleported to another host or process, but it is 825 817 not running. This is the paused variant of the 826 @c state.818 @c Teleporting state. 827 819 </desc> 828 820 </const> … … 849 841 </desc> 850 842 </const> 851 <const name="RestoringSnapshot" value="19"> 843 <const name="OnlineSnapshotting" value="19"> 844 <desc> 845 Like @c LiveSnapshotting, but the machine was paused when the 846 merging of differencing media was started. 847 </desc> 848 </const> 849 <const name="RestoringSnapshot" value="20"> 852 850 <desc> 853 851 A machine snapshot is being restored; this typically does not take long. 854 852 </desc> 855 853 </const> 856 <const name="DeletingSnapshot" value="2 0">854 <const name="DeletingSnapshot" value="21"> 857 855 <desc> 858 856 A machine snapshot is being deleted; this can take a long time since this … … 861 859 </desc> 862 860 </const> 863 <const name="SettingUp" value="2 1">861 <const name="SettingUp" value="22"> 864 862 <desc> 865 863 Lengthy setup operation is in progress. 866 864 </desc> 867 865 </const> 866 <const name="Snapshotting" value="23"> 867 <desc> 868 Taking an (offline) snapshot. 869 </desc> 870 </const> 868 871 869 872 <const name="FirstOnline" value="5" wsmap="suppress"> <!-- Running --> … … 872 875 </desc> 873 876 </const> 874 <const name="LastOnline" value="1 8" wsmap="suppress"> <!-- DeletingSnapshotPaused-->877 <const name="LastOnline" value="19" wsmap="suppress"> <!-- OnlineSnapshotting --> 875 878 <desc> 876 879 Pseudo-state: last online state (for use in relational expressions). … … 883 886 </desc> 884 887 </const> 885 <const name="LastTransient" value="2 1" wsmap="suppress"> <!-- SettingUp-->888 <const name="LastTransient" value="23" wsmap="suppress"> <!-- Snapshotting --> 886 889 <desc> 887 890 Pseudo-state: last transient state (for use in relational expressions). … … 1074 1077 <enum 1075 1078 name="LockType" 1076 uuid=" 168a6a8e-12fd-4878-a1f9-38a750a56089"1079 uuid="678aaf14-2815-4c3e-b20a-e86ed0216498" 1077 1080 > 1078 1081 <desc> 1079 1082 Used with <link to="IMachine::lockMachine" />. 1080 1083 </desc> 1084 <const name="Null" value="0"> 1085 <desc>Placeholder value, do not use when obtaining a lock.</desc> 1086 </const> 1087 <const name="Shared" value="1"> 1088 <desc>Request only a shared lock for remote-controlling the machine. 1089 Such a lock allows changing certain VM settings which can be safely 1090 modified for a running VM.</desc> 1091 </const> 1081 1092 <const name="Write" value="2"> 1082 1093 <desc>Lock the machine for writing. This requests an exclusive lock, i.e. … … 1085 1096 which implicitly holds the equivalent of a shared lock during the 1086 1097 entire VM runtime.</desc> 1087 </const>1088 <const name="Shared" value="1">1089 <desc>Request only a shared lock for remote-controlling the machine.1090 Such a lock allows changing certain VM settings which can be safely1091 modified for a running VM.</desc>1092 1098 </const> 1093 1099 <const name="VM" value="3"> … … 3586 3592 <interface 3587 3593 name="IInternalMachineControl" extends="$unknown" 3588 uuid=" 1470ff16-d7fa-448e-9c38-0352a36053bf"3594 uuid="f0b3bf6e-c609-4d5e-9fd7-77537a52c31b" 3589 3595 internal="yes" 3590 3596 wsmap="suppress" 3591 3597 > 3592 <method name="setRemoveSavedStateFile">3593 <desc>3594 Updates the flag whether the saved state file is removed on a3595 machine state change from Saved to PoweredOff.3596 </desc>3597 <param name="remove" type="boolean" dir="in"/>3598 </method>3599 3598 3600 3599 <method name="updateState"> … … 3758 3757 </method> 3759 3758 3760 <method name="beginSavingState">3761 <desc>3762 Called by the VM process to inform the server it wants to3763 save the current state and stop the VM execution.3764 </desc>3765 <param name="progress" type="IProgress" dir="out">3766 <desc>3767 Progress object created by VBoxSVC to wait until3768 the state is saved.3769 </desc>3770 </param>3771 <param name="stateFilePath" type="wstring" dir="out">3772 <desc>3773 File path the VM process must save the execution state to.3774 </desc>3775 </param>3776 </method>3777 3778 <method name="endSavingState">3779 <desc>3780 Called by the VM process to inform the server that saving3781 the state previously requested by #beginSavingState is either3782 successfully finished or there was a failure.3783 3784 <result name="VBOX_E_FILE_ERROR">3785 Settings file not accessible.3786 </result>3787 <result name="VBOX_E_XML_ERROR">3788 Could not parse the settings file.3789 </result>3790 3791 </desc>3792 3793 <param name="result" type="long" dir="in">3794 <desc>@c S_OK to indicate success.3795 </desc>3796 </param>3797 <param name="errMsg" type="wstring" dir="in">3798 <desc>@c human readable error message in case of failure.3799 </desc>3800 </param>3801 </method>3802 3803 <method name="adoptSavedState">3804 <desc>3805 Gets called by <link to="IConsole::adoptSavedState"/>.3806 <result name="VBOX_E_FILE_ERROR">3807 Invalid saved state file path.3808 </result>3809 </desc>3810 <param name="savedStateFile" type="wstring" dir="in">3811 <desc>Path to the saved state file to adopt.</desc>3812 </param>3813 </method>3814 3815 <method name="beginTakingSnapshot">3816 <desc>3817 Called from the VM process to request from the server to perform the3818 server-side actions of creating a snapshot (creating differencing images3819 and the snapshot object).3820 3821 <result name="VBOX_E_FILE_ERROR">3822 Settings file not accessible.3823 </result>3824 <result name="VBOX_E_XML_ERROR">3825 Could not parse the settings file.3826 </result>3827 </desc>3828 <param name="initiator" type="IConsole" dir="in">3829 <desc>The console object that initiated this call.</desc>3830 </param>3831 <param name="name" type="wstring" dir="in">3832 <desc>Snapshot name.</desc>3833 </param>3834 <param name="description" type="wstring" dir="in">3835 <desc>Snapshot description.</desc>3836 </param>3837 <param name="consoleProgress" type="IProgress" dir="in">3838 <desc>3839 Progress object created by the VM process tracking the3840 snapshot's progress. This has the following sub-operations:3841 <ul>3842 <li>setting up (weight 1);</li>3843 <li>one for each medium attachment that needs a differencing image (weight 1 each);</li>3844 <li>another one to copy the VM state (if offline with saved state, weight is VM memory size in MB);</li>3845 <li>another one to save the VM state (if online, weight is VM memory size in MB);</li>3846 <li>finishing up (weight 1)</li>3847 </ul>3848 </desc>3849 </param>3850 <param name="fTakingSnapshotOnline" type="boolean" dir="in">3851 <desc>3852 Whether this is an online snapshot (i.e. the machine is running).3853 </desc>3854 </param>3855 <param name="stateFilePath" type="wstring" dir="out">3856 <desc>3857 File path the VM process must save the execution state to.3858 </desc>3859 </param>3860 </method>3861 3862 <method name="endTakingSnapshot">3863 <desc>3864 Called by the VM process to inform the server that the snapshot3865 previously requested by #beginTakingSnapshot is either3866 successfully taken or there was a failure.3867 </desc>3868 3869 <param name="success" type="boolean" dir="in">3870 <desc>@c true to indicate success and @c false otherwise</desc>3871 </param>3872 </method>3873 3874 <method name="deleteSnapshot">3875 <desc>3876 Gets called by <link to="IConsole::deleteSnapshot"/>,3877 <link to="IConsole::deleteSnapshotAndAllChildren"/> and3878 <link to="IConsole::deleteSnapshotRange"/>.3879 <result name="VBOX_E_INVALID_OBJECT_STATE">3880 Snapshot has more than one child snapshot. Only possible if the3881 delete operation does not delete all children or the range does3882 not meet the linearity condition.3883 </result>3884 </desc>3885 <param name="initiator" type="IConsole" dir="in">3886 <desc>The console object that initiated this call.</desc>3887 </param>3888 <param name="startId" type="uuid" mod="string" dir="in">3889 <desc>UUID of the first snapshot to delete.</desc>3890 </param>3891 <param name="endId" type="uuid" mod="string" dir="in">3892 <desc>UUID of the last snapshot to delete.</desc>3893 </param>3894 <param name="deleteAllChildren" type="boolean" dir="in">3895 <desc>Whether all children should be deleted.</desc>3896 </param>3897 <param name="machineState" type="MachineState" dir="out">3898 <desc>New machine state after this operation is started.</desc>3899 </param>3900 <param name="progress" type="IProgress" dir="return">3901 <desc>Progress object to track the operation completion.</desc>3902 </param>3903 </method>3904 3905 3759 <method name="finishOnlineMergeMedium"> 3906 3760 <desc> … … 3908 3762 All necessary state information is available at the called object. 3909 3763 </desc> 3910 </method>3911 3912 <method name="restoreSnapshot">3913 <desc>3914 Gets called by <link to="IConsole::restoreSnapshot"/>.3915 </desc>3916 <param name="initiator" type="IConsole" dir="in">3917 <desc>The console object that initiated this call.</desc>3918 </param>3919 <param name="snapshot" type="ISnapshot" dir="in">3920 <desc>The snapshot to restore the VM state from.</desc>3921 </param>3922 <param name="machineState" type="MachineState" dir="out">3923 <desc>New machine state after this operation is started.</desc>3924 </param>3925 <param name="progress" type="IProgress" dir="return">3926 <desc>Progress object to track the operation completion.</desc>3927 </param>3928 3764 </method> 3929 3765 … … 4341 4177 <interface 4342 4178 name="IMachine" extends="$unknown" 4343 uuid=" 2280b3f8-0c33-4641-8bd5-ccecd1071b49"4179 uuid="bfe5287a-5fbc-4ceb-9f0e-7fb317e78681" 4344 4180 wsmap="managed" 4345 4181 wrap-hint-server-addinterfaces="IInternalMachineControl" … … 4888 4724 Current snapshot of this machine. This is @c null if the machine 4889 4725 currently has no snapshots. If it is not @c null, then it was 4890 set by one of <link to="IConsole::takeSnapshot" />, 4891 <link to="IConsole::deleteSnapshot" /> 4892 or <link to="IConsole::restoreSnapshot" />, depending on which 4893 was called last. See <link to="ISnapshot"/> for details. 4726 set by one of <link to="#takeSnapshot" />, <link to="#deleteSnapshot" /> 4727 or <link to="#restoreSnapshot" />, depending on which was called last. 4728 See <link to="ISnapshot"/> for details. 4894 4729 </desc> 4895 4730 </attribute> … … 4911 4746 4912 4747 <ul> 4913 <li><link to=" IConsole::restoreSnapshot"/>4748 <li><link to="#restoreSnapshot"/> 4914 4749 </li> 4915 <li><link to="IConsole::takeSnapshot"/> (issued on a 4916 "powered off" or "saved" machine, for which 4917 <link to="#settingsModified"/> returns @c false) 4750 <li><link to="#takeSnapshot"/> (issued on a "powered off" or "saved" 4751 machine, for which <link to="#settingsModified"/> returns @c false) 4918 4752 </li> 4919 4753 </ul> … … 7432 7266 </method> 7433 7267 7434 </interface>7435 7436 <interface7437 name="IEmulatedUSB" extends="$unknown"7438 uuid="38cc4dfd-8bb2-4d40-aebe-699eead8c2dd"7439 wsmap="managed"7440 >7441 <desc>7442 Manages emulated USB devices.7443 </desc>7444 7445 <method name="webcamAttach">7446 <desc>7447 Attaches the emulated USB webcam to the VM, which will use a host video capture device.7448 </desc>7449 <param name="path" type="wstring" dir="in">7450 <desc>The host path of the capture device to use.</desc>7451 </param>7452 <param name="settings" type="wstring" dir="in">7453 <desc>Optional settings.</desc>7454 </param>7455 </method>7456 7457 <method name="webcamDetach">7458 <desc>7459 Detaches the emulated USB webcam from the VM7460 </desc>7461 <param name="path" type="wstring" dir="in">7462 <desc>The host path of the capture device to detach.</desc>7463 </param>7464 </method>7465 7466 <attribute name="webcams" type="wstring" safearray="yes" readonly="yes">7467 <desc>Lists attached virtual webcams.</desc>7468 </attribute>7469 </interface>7470 7471 <!--7472 // IConsole7473 /////////////////////////////////////////////////////////////////////////7474 -->7475 7476 <interface7477 name="IVRDEServerInfo" extends="$unknown"7478 uuid="714434a1-58c3-4aab-9049-7652c5df113b"7479 wsmap="struct"7480 >7481 <desc>7482 Contains information about the remote desktop (VRDE) server capabilities and status.7483 This is used in the <link to="IConsole::VRDEServerInfo" /> attribute.7484 </desc>7485 7486 <attribute name="active" type="boolean" readonly="yes">7487 <desc>7488 Whether the remote desktop connection is active.7489 </desc>7490 </attribute>7491 7492 <attribute name="port" type="long" readonly="yes">7493 <desc>7494 VRDE server port number. If this property is equal to <tt>0</tt>, then7495 the VRDE server failed to start, usually because there are no free IP7496 ports to bind to. If this property is equal to <tt>-1</tt>, then the VRDE7497 server has not yet been started.7498 </desc>7499 </attribute>7500 7501 <attribute name="numberOfClients" type="unsigned long" readonly="yes">7502 <desc>7503 How many times a client connected.7504 </desc>7505 </attribute>7506 7507 <attribute name="beginTime" type="long long" readonly="yes">7508 <desc>7509 When the last connection was established, in milliseconds since 1970-01-01 UTC.7510 </desc>7511 </attribute>7512 7513 <attribute name="endTime" type="long long" readonly="yes">7514 <desc>7515 When the last connection was terminated or the current time, if7516 connection is still active, in milliseconds since 1970-01-01 UTC.7517 </desc>7518 </attribute>7519 7520 <attribute name="bytesSent" type="long long" readonly="yes">7521 <desc>7522 How many bytes were sent in last or current, if still active, connection.7523 </desc>7524 </attribute>7525 7526 <attribute name="bytesSentTotal" type="long long" readonly="yes">7527 <desc>7528 How many bytes were sent in all connections.7529 </desc>7530 </attribute>7531 7532 <attribute name="bytesReceived" type="long long" readonly="yes">7533 <desc>7534 How many bytes were received in last or current, if still active, connection.7535 </desc>7536 </attribute>7537 7538 <attribute name="bytesReceivedTotal" type="long long" readonly="yes">7539 <desc>7540 How many bytes were received in all connections.7541 </desc>7542 </attribute>7543 7544 <attribute name="user" type="wstring" readonly="yes">7545 <desc>7546 Login user name supplied by the client.7547 </desc>7548 </attribute>7549 7550 <attribute name="domain" type="wstring" readonly="yes">7551 <desc>7552 Login domain name supplied by the client.7553 </desc>7554 </attribute>7555 7556 <attribute name="clientName" type="wstring" readonly="yes">7557 <desc>7558 The client name supplied by the client.7559 </desc>7560 </attribute>7561 7562 <attribute name="clientIP" type="wstring" readonly="yes">7563 <desc>7564 The IP address of the client.7565 </desc>7566 </attribute>7567 7568 <attribute name="clientVersion" type="unsigned long" readonly="yes">7569 <desc>7570 The client software version number.7571 </desc>7572 </attribute>7573 7574 <attribute name="encryptionStyle" type="unsigned long" readonly="yes">7575 <desc>7576 Public key exchange method used when connection was established.7577 Values: 0 - RDP4 public key exchange scheme.7578 1 - X509 certificates were sent to client.7579 </desc>7580 </attribute>7581 7582 </interface>7583 7584 <interface7585 name="IConsole" extends="$unknown"7586 uuid="080505f4-bca9-45aa-ab95-030036b665e6"7587 wsmap="managed"7588 >7589 <desc>7590 The IConsole interface represents an interface to control virtual7591 machine execution.7592 7593 A console object gets created when a machine has been locked for a7594 particular session (client process) using <link to="IMachine::lockMachine" />7595 or <link to="IMachine::launchVMProcess"/>. The console object can7596 then be found in the session's <link to="ISession::console" /> attribute.7597 7598 Methods of the IConsole interface allow the caller to query the current7599 virtual machine execution state, pause the machine or power it down, save7600 the machine state or take a snapshot, attach and detach removable media7601 and so on.7602 7603 <see><link to="ISession"/></see>7604 </desc>7605 7606 <attribute name="machine" type="IMachine" readonly="yes">7607 <desc>7608 Machine object for this console session.7609 <note>7610 This is a convenience property, it has the same value as7611 <link to="ISession::machine"/> of the corresponding session7612 object.7613 </note>7614 </desc>7615 </attribute>7616 7617 <attribute name="state" type="MachineState" readonly="yes">7618 <desc>7619 Current execution state of the machine.7620 <note>7621 This property always returns the same value as the corresponding7622 property of the IMachine object for this console session.7623 For the process that owns (executes) the VM, this is the7624 preferable way of querying the VM state, because no IPC7625 calls are made.7626 </note>7627 </desc>7628 </attribute>7629 7630 <attribute name="guest" type="IGuest" readonly="yes">7631 <desc>Guest object.</desc>7632 </attribute>7633 7634 <attribute name="keyboard" type="IKeyboard" readonly="yes">7635 <desc>7636 Virtual keyboard object.7637 <note>7638 If the machine is not running, any attempt to use7639 the returned object will result in an error.7640 </note>7641 </desc>7642 </attribute>7643 7644 <attribute name="mouse" type="IMouse" readonly="yes">7645 <desc>7646 Virtual mouse object.7647 <note>7648 If the machine is not running, any attempt to use7649 the returned object will result in an error.7650 </note>7651 </desc>7652 </attribute>7653 7654 <attribute name="display" type="IDisplay" readonly="yes">7655 <desc>Virtual display object.7656 <note>7657 If the machine is not running, any attempt to use7658 the returned object will result in an error.7659 </note>7660 </desc>7661 </attribute>7662 7663 <attribute name="debugger" type="IMachineDebugger" readonly="yes">7664 <desc>Debugging interface.</desc>7665 </attribute>7666 7667 <attribute name="USBDevices" type="IUSBDevice" readonly="yes" safearray="yes">7668 <desc>7669 Collection of USB devices currently attached to the virtual7670 USB controller.7671 <note>7672 The collection is empty if the machine is not running.7673 </note>7674 </desc>7675 </attribute>7676 7677 <attribute name="remoteUSBDevices" type="IHostUSBDevice" readonly="yes" safearray="yes">7678 <desc>7679 List of USB devices currently attached to the remote VRDE client.7680 Once a new device is physically attached to the remote host computer,7681 it appears in this list and remains there until detached.7682 </desc>7683 </attribute>7684 7685 <attribute name="sharedFolders" type="ISharedFolder" readonly="yes" safearray="yes">7686 <desc>7687 Collection of shared folders for the current session. These folders7688 are called transient shared folders because they are available to the7689 guest OS running inside the associated virtual machine only for the7690 duration of the session (as opposed to7691 <link to="IMachine::sharedFolders"/> which represent permanent shared7692 folders). When the session is closed (e.g. the machine is powered down),7693 these folders are automatically discarded.7694 7695 New shared folders are added to the collection using7696 <link to="#createSharedFolder"/>. Existing shared folders can be7697 removed using <link to="#removeSharedFolder"/>.7698 </desc>7699 </attribute>7700 7701 <attribute name="VRDEServerInfo" type="IVRDEServerInfo" readonly="yes">7702 <desc>7703 Interface that provides information on Remote Desktop Extension (VRDE) connection.7704 </desc>7705 </attribute>7706 7707 <attribute name="eventSource" type="IEventSource" readonly="yes">7708 <desc>7709 Event source for console events.7710 </desc>7711 </attribute>7712 7713 <attribute name="attachedPCIDevices" type="IPCIDeviceAttachment" readonly="yes" safearray="yes">7714 <desc>Array of PCI devices attached to this machine.</desc>7715 </attribute>7716 7717 <attribute name="useHostClipboard" type="boolean">7718 <desc>7719 Whether the guest clipboard should be connected to the host one or7720 whether it should only be allowed access to the VRDE clipboard. This7721 setting may not affect existing guest clipboard connections which7722 are already connected to the host clipboard.7723 </desc>7724 </attribute>7725 7726 <attribute name="emulatedUSB" type="IEmulatedUSB" readonly="yes">7727 <desc>7728 Interface that manages emulated USB devices.7729 </desc>7730 </attribute>7731 7732 <method name="powerUp">7733 <desc>7734 Starts the virtual machine execution using the current machine7735 state (that is, its current execution state, current settings and7736 current storage devices).7737 7738 <note>7739 This method is only useful for front-ends that want to actually7740 execute virtual machines in their own process (like the VirtualBox7741 or VBoxSDL front-ends). Unless you are intending to write such a7742 front-end, do not call this method. If you simply want to7743 start virtual machine execution using one of the existing front-ends7744 (for example the VirtualBox GUI or headless server), use7745 <link to="IMachine::launchVMProcess"/> instead; these7746 front-ends will power up the machine automatically for you.7747 </note>7748 7749 If the machine is powered off or aborted, the execution will7750 start from the beginning (as if the real hardware were just7751 powered on).7752 7753 If the machine is in the <link to="MachineState_Saved"/> state,7754 it will continue its execution the point where the state has7755 been saved.7756 7757 If the machine <link to="IMachine::teleporterEnabled"/> property is7758 enabled on the machine being powered up, the machine will wait for an7759 incoming teleportation in the <link to="MachineState_TeleportingIn"/>7760 state. The returned progress object will have at least three7761 operations where the last three are defined as: (1) powering up and7762 starting TCP server, (2) waiting for incoming teleportations, and7763 (3) perform teleportation. These operations will be reflected as the7764 last three operations of the progress objected returned by7765 <link to="IMachine::launchVMProcess"/> as well.7766 7767 <see><link to="#saveState"/></see>7768 7769 <result name="VBOX_E_INVALID_VM_STATE">7770 Virtual machine already running.7771 </result>7772 <result name="VBOX_E_HOST_ERROR">7773 Host interface does not exist or name not set.7774 </result>7775 <result name="VBOX_E_FILE_ERROR">7776 Invalid saved state file.7777 </result>7778 </desc>7779 <param name="progress" type="IProgress" dir="return">7780 <desc>Progress object to track the operation completion.</desc>7781 </param>7782 </method>7783 7784 <method name="powerUpPaused">7785 <desc>7786 Identical to powerUp except that the VM will enter the7787 <link to="MachineState_Paused"/> state, instead of7788 <link to="MachineState_Running"/>.7789 7790 <see><link to="#powerUp"/></see>7791 <result name="VBOX_E_INVALID_VM_STATE">7792 Virtual machine already running.7793 </result>7794 <result name="VBOX_E_HOST_ERROR">7795 Host interface does not exist or name not set.7796 </result>7797 <result name="VBOX_E_FILE_ERROR">7798 Invalid saved state file.7799 </result>7800 </desc>7801 <param name="progress" type="IProgress" dir="return">7802 <desc>Progress object to track the operation completion.</desc>7803 </param>7804 </method>7805 7806 <method name="powerDown">7807 <desc>7808 Initiates the power down procedure to stop the virtual machine7809 execution.7810 7811 The completion of the power down procedure is tracked using the returned7812 IProgress object. After the operation is complete, the machine will go7813 to the PoweredOff state.7814 <result name="VBOX_E_INVALID_VM_STATE">7815 Virtual machine must be Running, Paused or Stuck to be powered down.7816 </result>7817 </desc>7818 <param name="progress" type="IProgress" dir="return">7819 <desc>Progress object to track the operation completion.</desc>7820 </param>7821 </method>7822 7823 <method name="reset">7824 <desc>Resets the virtual machine.7825 <result name="VBOX_E_INVALID_VM_STATE">7826 Virtual machine not in Running state.7827 </result>7828 <result name="VBOX_E_VM_ERROR">7829 Virtual machine error in reset operation.7830 </result>7831 </desc>7832 </method>7833 7834 <method name="pause">7835 <desc>Pauses the virtual machine execution.7836 <result name="VBOX_E_INVALID_VM_STATE">7837 Virtual machine not in Running state.7838 </result>7839 <result name="VBOX_E_VM_ERROR">7840 Virtual machine error in suspend operation.7841 </result>7842 </desc>7843 </method>7844 7845 <method name="resume">7846 <desc>Resumes the virtual machine execution.7847 <result name="VBOX_E_INVALID_VM_STATE">7848 Virtual machine not in Paused state.7849 </result>7850 <result name="VBOX_E_VM_ERROR">7851 Virtual machine error in resume operation.7852 </result>7853 </desc>7854 </method>7855 7856 <method name="powerButton">7857 <desc>Sends the ACPI power button event to the guest.7858 <result name="VBOX_E_INVALID_VM_STATE">7859 Virtual machine not in Running state.7860 </result>7861 <result name="VBOX_E_PDM_ERROR">7862 Controlled power off failed.7863 </result>7864 </desc>7865 </method>7866 7867 <method name="sleepButton">7868 <desc>Sends the ACPI sleep button event to the guest.7869 <result name="VBOX_E_INVALID_VM_STATE">7870 Virtual machine not in Running state.7871 </result>7872 <result name="VBOX_E_PDM_ERROR">7873 Sending sleep button event failed.7874 </result>7875 </desc>7876 </method>7877 7878 <method name="getPowerButtonHandled">7879 <desc>Checks if the last power button event was handled by guest.7880 <result name="VBOX_E_PDM_ERROR">7881 Checking if the event was handled by the guest OS failed.7882 </result>7883 </desc>7884 <param name="handled" type="boolean" dir="return"/>7885 </method>7886 7887 <method name="getGuestEnteredACPIMode">7888 <desc>Checks if the guest entered the ACPI mode G0 (working) or7889 G1 (sleeping). If this method returns @c false, the guest will7890 most likely not respond to external ACPI events.7891 <result name="VBOX_E_INVALID_VM_STATE">7892 Virtual machine not in Running state.7893 </result>7894 </desc>7895 <param name="entered" type="boolean" dir="return"/>7896 </method>7897 7898 7268 <method name="saveState"> 7899 7269 <desc> … … 7914 7284 <note> 7915 7285 On success, this method implicitly calls 7916 <link to=" IMachine::saveSettings"/> to save all current machine7286 <link to="#saveSettings"/> to save all current machine 7917 7287 settings (including runtime changes to the DVD medium, etc.). 7918 7288 Together with the impossibility to change any VM settings when it is … … 7951 7321 The specified saved state file path may be absolute or relative to the 7952 7322 folder the VM normally saves the state to (usually, 7953 <link to=" IMachine::snapshotFolder"/>).7323 <link to="#snapshotFolder"/>). 7954 7324 7955 7325 <note> … … 7985 7355 re-inserted into a machine using <link to="#adoptSavedState" />. 7986 7356 The location of the file can be found in the 7987 <link to=" IMachine::stateFilePath" /> attribute.7357 <link to="#stateFilePath" /> attribute. 7988 7358 <result name="VBOX_E_INVALID_VM_STATE"> 7989 7359 Virtual machine not in state Saved. … … 7992 7362 <param name="fRemoveFile" type="boolean" dir="in" > 7993 7363 <desc>Whether to also remove the saved state file.</desc> 7994 </param>7995 </method>7996 7997 <method name="getDeviceActivity">7998 <desc>7999 Gets the current activity type of given devices or device groups.8000 <result name="E_INVALIDARG">8001 Invalid device type.8002 </result>8003 </desc>8004 <param name="type" type="DeviceType" safearray="yes" dir="in"/>8005 <param name="activity" type="DeviceActivity" safearray="yes" dir="return"/>8006 </method>8007 8008 <method name="attachUSBDevice">8009 <desc>8010 Attaches a host USB device with the given UUID to the8011 USB controller of the virtual machine.8012 8013 The device needs to be in one of the following states:8014 <link to="USBDeviceState_Busy"/>,8015 <link to="USBDeviceState_Available"/> or8016 <link to="USBDeviceState_Held"/>,8017 otherwise an error is immediately returned.8018 8019 When the device state is8020 <link to="USBDeviceState_Busy">Busy</link>, an error may also8021 be returned if the host computer refuses to release it for some reason.8022 8023 <see><link to="IUSBDeviceFilters::deviceFilters"/>,8024 <link to="USBDeviceState"/></see>8025 <result name="VBOX_E_INVALID_VM_STATE">8026 Virtual machine state neither Running nor Paused.8027 </result>8028 <result name="VBOX_E_PDM_ERROR">8029 Virtual machine does not have a USB controller.8030 </result>8031 </desc>8032 <param name="id" type="uuid" mod="string" dir="in">8033 <desc>UUID of the host USB device to attach.</desc>8034 </param>8035 <param name="captureFilename" type="wstring" dir="in">8036 <desc>Filename to capture the USB traffic to.</desc>8037 </param>8038 </method>8039 8040 <method name="detachUSBDevice">8041 <desc>8042 Detaches an USB device with the given UUID from the USB controller8043 of the virtual machine.8044 8045 After this method succeeds, the VirtualBox server re-initiates8046 all USB filters as if the device were just physically attached8047 to the host, but filters of this machine are ignored to avoid8048 a possible automatic re-attachment.8049 8050 <see><link to="IUSBDeviceFilters::deviceFilters"/>,8051 <link to="USBDeviceState"/></see>8052 8053 <result name="VBOX_E_PDM_ERROR">8054 Virtual machine does not have a USB controller.8055 </result>8056 <result name="E_INVALIDARG">8057 USB device not attached to this virtual machine.8058 </result>8059 </desc>8060 <param name="id" type="uuid" mod="string" dir="in">8061 <desc>UUID of the USB device to detach.</desc>8062 </param>8063 <param name="device" type="IUSBDevice" dir="return">8064 <desc>Detached USB device.</desc>8065 </param>8066 </method>8067 8068 <method name="findUSBDeviceByAddress">8069 <desc>8070 Searches for a USB device with the given host address.8071 8072 <result name="VBOX_E_OBJECT_NOT_FOUND">8073 Given @c name does not correspond to any USB device.8074 </result>8075 8076 <see><link to="IUSBDevice::address"/></see>8077 </desc>8078 <param name="name" type="wstring" dir="in">8079 <desc>8080 Address of the USB device (as assigned by the host) to8081 search for.8082 </desc>8083 </param>8084 <param name="device" type="IUSBDevice" dir="return">8085 <desc>Found USB device object.</desc>8086 </param>8087 </method>8088 8089 <method name="findUSBDeviceById">8090 <desc>8091 Searches for a USB device with the given UUID.8092 8093 <result name="VBOX_E_OBJECT_NOT_FOUND">8094 Given @c id does not correspond to any USB device.8095 </result>8096 8097 <see><link to="IUSBDevice::id"/></see>8098 </desc>8099 <param name="id" type="uuid" mod="string" dir="in">8100 <desc>UUID of the USB device to search for.</desc>8101 </param>8102 <param name="device" type="IUSBDevice" dir="return">8103 <desc>Found USB device object.</desc>8104 </param>8105 </method>8106 8107 <method name="createSharedFolder">8108 <desc>8109 Creates a transient new shared folder by associating the given logical8110 name with the given host path, adds it to the collection of shared8111 folders and starts sharing it. Refer to the description of8112 <link to="ISharedFolder"/> to read more about logical names.8113 8114 <result name="VBOX_E_INVALID_VM_STATE">8115 Virtual machine in Saved state or currently changing state.8116 </result>8117 <result name="VBOX_E_FILE_ERROR">8118 Shared folder already exists or not accessible.8119 </result>8120 </desc>8121 <param name="name" type="wstring" dir="in">8122 <desc>Unique logical name of the shared folder.</desc>8123 </param>8124 <param name="hostPath" type="wstring" dir="in">8125 <desc>Full path to the shared folder in the host file system.</desc>8126 </param>8127 <param name="writable" type="boolean" dir="in">8128 <desc>Whether the share is writable or readonly</desc>8129 </param>8130 <param name="automount" type="boolean" dir="in">8131 <desc>Whether the share gets automatically mounted by the guest8132 or not.</desc>8133 </param>8134 </method>8135 8136 <method name="removeSharedFolder">8137 <desc>8138 Removes a transient shared folder with the given name previously8139 created by <link to="#createSharedFolder"/> from the collection of8140 shared folders and stops sharing it.8141 <result name="VBOX_E_INVALID_VM_STATE">8142 Virtual machine in Saved state or currently changing state.8143 </result>8144 <result name="VBOX_E_FILE_ERROR">8145 Shared folder does not exists.8146 </result>8147 </desc>8148 <param name="name" type="wstring" dir="in">8149 <desc>Logical name of the shared folder to remove.</desc>8150 7364 </param> 8151 7365 </method> … … 8165 7379 8166 7380 The taken snapshot is always based on the 8167 <link to=" IMachine::currentSnapshot">current snapshot</link>7381 <link to="#currentSnapshot">current snapshot</link> 8168 7382 of the associated virtual machine and becomes a new current snapshot. 8169 7383 8170 7384 <note> 8171 This method implicitly calls <link to=" IMachine::saveSettings"/> to7385 This method implicitly calls <link to="#saveSettings"/> to 8172 7386 save all current machine settings before taking an offline snapshot. 8173 7387 </note> … … 8182 7396 <param name="description" type="wstring" dir="in"> 8183 7397 <desc>Optional description of the snapshot.</desc> 7398 </param> 7399 <param name="pause" type="boolean" dir="in"> 7400 <desc>Whether the VM should be paused while taking the snapshot. Only 7401 relevant when the VM is running, and distinguishes between online 7402 (@c true) and live (@c false) snapshots. When the VM is not running 7403 the result is always an offline snapshot.</desc> 8184 7404 </param> 8185 7405 <param name="progress" type="IProgress" dir="return"> … … 8210 7430 If the deleted snapshot is the first or current snapshot, then the 8211 7431 respective IMachine attributes will be adjusted. Deleting the current 8212 snapshot will also implicitly call <link to=" IMachine::saveSettings"/>7432 snapshot will also implicitly call <link to="#saveSettings"/> 8213 7433 to make all current machine settings permanent. 8214 7434 … … 8233 7453 </ul> 8234 7454 8235 The virtual machine's <link to=" IMachine::state">state</link> is7455 The virtual machine's <link to="#state">state</link> is 8236 7456 changed to "DeletingSnapshot", "DeletingSnapshotOnline" or 8237 7457 "DeletingSnapshotPaused" while this operation is in progress. … … 8366 7586 <param name="progress" type="IProgress" dir="return"> 8367 7587 <desc>Progress object to track the operation completion.</desc> 7588 </param> 7589 </method> 7590 7591 </interface> 7592 7593 <interface 7594 name="IEmulatedUSB" extends="$unknown" 7595 uuid="38cc4dfd-8bb2-4d40-aebe-699eead8c2dd" 7596 wsmap="managed" 7597 > 7598 <desc> 7599 Manages emulated USB devices. 7600 </desc> 7601 7602 <method name="webcamAttach"> 7603 <desc> 7604 Attaches the emulated USB webcam to the VM, which will use a host video capture device. 7605 </desc> 7606 <param name="path" type="wstring" dir="in"> 7607 <desc>The host path of the capture device to use.</desc> 7608 </param> 7609 <param name="settings" type="wstring" dir="in"> 7610 <desc>Optional settings.</desc> 7611 </param> 7612 </method> 7613 7614 <method name="webcamDetach"> 7615 <desc> 7616 Detaches the emulated USB webcam from the VM 7617 </desc> 7618 <param name="path" type="wstring" dir="in"> 7619 <desc>The host path of the capture device to detach.</desc> 7620 </param> 7621 </method> 7622 7623 <attribute name="webcams" type="wstring" safearray="yes" readonly="yes"> 7624 <desc>Lists attached virtual webcams.</desc> 7625 </attribute> 7626 </interface> 7627 7628 <!-- 7629 // IConsole 7630 ///////////////////////////////////////////////////////////////////////// 7631 --> 7632 7633 <interface 7634 name="IVRDEServerInfo" extends="$unknown" 7635 uuid="714434a1-58c3-4aab-9049-7652c5df113b" 7636 wsmap="struct" 7637 > 7638 <desc> 7639 Contains information about the remote desktop (VRDE) server capabilities and status. 7640 This is used in the <link to="IConsole::VRDEServerInfo" /> attribute. 7641 </desc> 7642 7643 <attribute name="active" type="boolean" readonly="yes"> 7644 <desc> 7645 Whether the remote desktop connection is active. 7646 </desc> 7647 </attribute> 7648 7649 <attribute name="port" type="long" readonly="yes"> 7650 <desc> 7651 VRDE server port number. If this property is equal to <tt>0</tt>, then 7652 the VRDE server failed to start, usually because there are no free IP 7653 ports to bind to. If this property is equal to <tt>-1</tt>, then the VRDE 7654 server has not yet been started. 7655 </desc> 7656 </attribute> 7657 7658 <attribute name="numberOfClients" type="unsigned long" readonly="yes"> 7659 <desc> 7660 How many times a client connected. 7661 </desc> 7662 </attribute> 7663 7664 <attribute name="beginTime" type="long long" readonly="yes"> 7665 <desc> 7666 When the last connection was established, in milliseconds since 1970-01-01 UTC. 7667 </desc> 7668 </attribute> 7669 7670 <attribute name="endTime" type="long long" readonly="yes"> 7671 <desc> 7672 When the last connection was terminated or the current time, if 7673 connection is still active, in milliseconds since 1970-01-01 UTC. 7674 </desc> 7675 </attribute> 7676 7677 <attribute name="bytesSent" type="long long" readonly="yes"> 7678 <desc> 7679 How many bytes were sent in last or current, if still active, connection. 7680 </desc> 7681 </attribute> 7682 7683 <attribute name="bytesSentTotal" type="long long" readonly="yes"> 7684 <desc> 7685 How many bytes were sent in all connections. 7686 </desc> 7687 </attribute> 7688 7689 <attribute name="bytesReceived" type="long long" readonly="yes"> 7690 <desc> 7691 How many bytes were received in last or current, if still active, connection. 7692 </desc> 7693 </attribute> 7694 7695 <attribute name="bytesReceivedTotal" type="long long" readonly="yes"> 7696 <desc> 7697 How many bytes were received in all connections. 7698 </desc> 7699 </attribute> 7700 7701 <attribute name="user" type="wstring" readonly="yes"> 7702 <desc> 7703 Login user name supplied by the client. 7704 </desc> 7705 </attribute> 7706 7707 <attribute name="domain" type="wstring" readonly="yes"> 7708 <desc> 7709 Login domain name supplied by the client. 7710 </desc> 7711 </attribute> 7712 7713 <attribute name="clientName" type="wstring" readonly="yes"> 7714 <desc> 7715 The client name supplied by the client. 7716 </desc> 7717 </attribute> 7718 7719 <attribute name="clientIP" type="wstring" readonly="yes"> 7720 <desc> 7721 The IP address of the client. 7722 </desc> 7723 </attribute> 7724 7725 <attribute name="clientVersion" type="unsigned long" readonly="yes"> 7726 <desc> 7727 The client software version number. 7728 </desc> 7729 </attribute> 7730 7731 <attribute name="encryptionStyle" type="unsigned long" readonly="yes"> 7732 <desc> 7733 Public key exchange method used when connection was established. 7734 Values: 0 - RDP4 public key exchange scheme. 7735 1 - X509 certificates were sent to client. 7736 </desc> 7737 </attribute> 7738 7739 </interface> 7740 7741 <interface 7742 name="IConsole" extends="$unknown" 7743 uuid="650b5f05-8258-4ee9-b518-89c515ca5dd9" 7744 wsmap="managed" 7745 > 7746 <desc> 7747 The IConsole interface represents an interface to control virtual 7748 machine execution. 7749 7750 A console object gets created when a machine has been locked for a 7751 particular session (client process) using <link to="IMachine::lockMachine" /> 7752 or <link to="IMachine::launchVMProcess"/>. The console object can 7753 then be found in the session's <link to="ISession::console" /> attribute. 7754 7755 Methods of the IConsole interface allow the caller to query the current 7756 virtual machine execution state, pause the machine or power it down, save 7757 the machine state or take a snapshot, attach and detach removable media 7758 and so on. 7759 7760 <see><link to="ISession"/></see> 7761 </desc> 7762 7763 <attribute name="machine" type="IMachine" readonly="yes"> 7764 <desc> 7765 Machine object for this console session. 7766 <note> 7767 This is a convenience property, it has the same value as 7768 <link to="ISession::machine"/> of the corresponding session 7769 object. 7770 </note> 7771 </desc> 7772 </attribute> 7773 7774 <attribute name="state" type="MachineState" readonly="yes"> 7775 <desc> 7776 Current execution state of the machine. 7777 <note> 7778 This property always returns the same value as the corresponding 7779 property of the IMachine object for this console session. 7780 For the process that owns (executes) the VM, this is the 7781 preferable way of querying the VM state, because no IPC 7782 calls are made. 7783 </note> 7784 </desc> 7785 </attribute> 7786 7787 <attribute name="guest" type="IGuest" readonly="yes"> 7788 <desc>Guest object.</desc> 7789 </attribute> 7790 7791 <attribute name="keyboard" type="IKeyboard" readonly="yes"> 7792 <desc> 7793 Virtual keyboard object. 7794 <note> 7795 If the machine is not running, any attempt to use 7796 the returned object will result in an error. 7797 </note> 7798 </desc> 7799 </attribute> 7800 7801 <attribute name="mouse" type="IMouse" readonly="yes"> 7802 <desc> 7803 Virtual mouse object. 7804 <note> 7805 If the machine is not running, any attempt to use 7806 the returned object will result in an error. 7807 </note> 7808 </desc> 7809 </attribute> 7810 7811 <attribute name="display" type="IDisplay" readonly="yes"> 7812 <desc>Virtual display object. 7813 <note> 7814 If the machine is not running, any attempt to use 7815 the returned object will result in an error. 7816 </note> 7817 </desc> 7818 </attribute> 7819 7820 <attribute name="debugger" type="IMachineDebugger" readonly="yes"> 7821 <desc>Debugging interface.</desc> 7822 </attribute> 7823 7824 <attribute name="USBDevices" type="IUSBDevice" readonly="yes" safearray="yes"> 7825 <desc> 7826 Collection of USB devices currently attached to the virtual 7827 USB controller. 7828 <note> 7829 The collection is empty if the machine is not running. 7830 </note> 7831 </desc> 7832 </attribute> 7833 7834 <attribute name="remoteUSBDevices" type="IHostUSBDevice" readonly="yes" safearray="yes"> 7835 <desc> 7836 List of USB devices currently attached to the remote VRDE client. 7837 Once a new device is physically attached to the remote host computer, 7838 it appears in this list and remains there until detached. 7839 </desc> 7840 </attribute> 7841 7842 <attribute name="sharedFolders" type="ISharedFolder" readonly="yes" safearray="yes"> 7843 <desc> 7844 Collection of shared folders for the current session. These folders 7845 are called transient shared folders because they are available to the 7846 guest OS running inside the associated virtual machine only for the 7847 duration of the session (as opposed to 7848 <link to="IMachine::sharedFolders"/> which represent permanent shared 7849 folders). When the session is closed (e.g. the machine is powered down), 7850 these folders are automatically discarded. 7851 7852 New shared folders are added to the collection using 7853 <link to="#createSharedFolder"/>. Existing shared folders can be 7854 removed using <link to="#removeSharedFolder"/>. 7855 </desc> 7856 </attribute> 7857 7858 <attribute name="VRDEServerInfo" type="IVRDEServerInfo" readonly="yes"> 7859 <desc> 7860 Interface that provides information on Remote Desktop Extension (VRDE) connection. 7861 </desc> 7862 </attribute> 7863 7864 <attribute name="eventSource" type="IEventSource" readonly="yes"> 7865 <desc> 7866 Event source for console events. 7867 </desc> 7868 </attribute> 7869 7870 <attribute name="attachedPCIDevices" type="IPCIDeviceAttachment" readonly="yes" safearray="yes"> 7871 <desc>Array of PCI devices attached to this machine.</desc> 7872 </attribute> 7873 7874 <attribute name="useHostClipboard" type="boolean"> 7875 <desc> 7876 Whether the guest clipboard should be connected to the host one or 7877 whether it should only be allowed access to the VRDE clipboard. This 7878 setting may not affect existing guest clipboard connections which 7879 are already connected to the host clipboard. 7880 </desc> 7881 </attribute> 7882 7883 <attribute name="emulatedUSB" type="IEmulatedUSB" readonly="yes"> 7884 <desc> 7885 Interface that manages emulated USB devices. 7886 </desc> 7887 </attribute> 7888 7889 <method name="powerUp"> 7890 <desc> 7891 Starts the virtual machine execution using the current machine 7892 state (that is, its current execution state, current settings and 7893 current storage devices). 7894 7895 <note> 7896 This method is only useful for front-ends that want to actually 7897 execute virtual machines in their own process (like the VirtualBox 7898 or VBoxSDL front-ends). Unless you are intending to write such a 7899 front-end, do not call this method. If you simply want to 7900 start virtual machine execution using one of the existing front-ends 7901 (for example the VirtualBox GUI or headless server), use 7902 <link to="IMachine::launchVMProcess"/> instead; these 7903 front-ends will power up the machine automatically for you. 7904 </note> 7905 7906 If the machine is powered off or aborted, the execution will 7907 start from the beginning (as if the real hardware were just 7908 powered on). 7909 7910 If the machine is in the <link to="MachineState_Saved"/> state, 7911 it will continue its execution the point where the state has 7912 been saved. 7913 7914 If the machine <link to="IMachine::teleporterEnabled"/> property is 7915 enabled on the machine being powered up, the machine will wait for an 7916 incoming teleportation in the <link to="MachineState_TeleportingIn"/> 7917 state. The returned progress object will have at least three 7918 operations where the last three are defined as: (1) powering up and 7919 starting TCP server, (2) waiting for incoming teleportations, and 7920 (3) perform teleportation. These operations will be reflected as the 7921 last three operations of the progress objected returned by 7922 <link to="IMachine::launchVMProcess"/> as well. 7923 7924 <see><link to="IMachine::saveState"/></see> 7925 7926 <result name="VBOX_E_INVALID_VM_STATE"> 7927 Virtual machine already running. 7928 </result> 7929 <result name="VBOX_E_HOST_ERROR"> 7930 Host interface does not exist or name not set. 7931 </result> 7932 <result name="VBOX_E_FILE_ERROR"> 7933 Invalid saved state file. 7934 </result> 7935 </desc> 7936 <param name="progress" type="IProgress" dir="return"> 7937 <desc>Progress object to track the operation completion.</desc> 7938 </param> 7939 </method> 7940 7941 <method name="powerUpPaused"> 7942 <desc> 7943 Identical to powerUp except that the VM will enter the 7944 <link to="MachineState_Paused"/> state, instead of 7945 <link to="MachineState_Running"/>. 7946 7947 <see><link to="#powerUp"/></see> 7948 <result name="VBOX_E_INVALID_VM_STATE"> 7949 Virtual machine already running. 7950 </result> 7951 <result name="VBOX_E_HOST_ERROR"> 7952 Host interface does not exist or name not set. 7953 </result> 7954 <result name="VBOX_E_FILE_ERROR"> 7955 Invalid saved state file. 7956 </result> 7957 </desc> 7958 <param name="progress" type="IProgress" dir="return"> 7959 <desc>Progress object to track the operation completion.</desc> 7960 </param> 7961 </method> 7962 7963 <method name="powerDown"> 7964 <desc> 7965 Initiates the power down procedure to stop the virtual machine 7966 execution. 7967 7968 The completion of the power down procedure is tracked using the returned 7969 IProgress object. After the operation is complete, the machine will go 7970 to the PoweredOff state. 7971 <result name="VBOX_E_INVALID_VM_STATE"> 7972 Virtual machine must be Running, Paused or Stuck to be powered down. 7973 </result> 7974 </desc> 7975 <param name="progress" type="IProgress" dir="return"> 7976 <desc>Progress object to track the operation completion.</desc> 7977 </param> 7978 </method> 7979 7980 <method name="reset"> 7981 <desc>Resets the virtual machine. 7982 <result name="VBOX_E_INVALID_VM_STATE"> 7983 Virtual machine not in Running state. 7984 </result> 7985 <result name="VBOX_E_VM_ERROR"> 7986 Virtual machine error in reset operation. 7987 </result> 7988 </desc> 7989 </method> 7990 7991 <method name="pause"> 7992 <desc>Pauses the virtual machine execution. 7993 <result name="VBOX_E_INVALID_VM_STATE"> 7994 Virtual machine not in Running state. 7995 </result> 7996 <result name="VBOX_E_VM_ERROR"> 7997 Virtual machine error in suspend operation. 7998 </result> 7999 </desc> 8000 </method> 8001 8002 <method name="resume"> 8003 <desc>Resumes the virtual machine execution. 8004 <result name="VBOX_E_INVALID_VM_STATE"> 8005 Virtual machine not in Paused state. 8006 </result> 8007 <result name="VBOX_E_VM_ERROR"> 8008 Virtual machine error in resume operation. 8009 </result> 8010 </desc> 8011 </method> 8012 8013 <method name="powerButton"> 8014 <desc>Sends the ACPI power button event to the guest. 8015 <result name="VBOX_E_INVALID_VM_STATE"> 8016 Virtual machine not in Running state. 8017 </result> 8018 <result name="VBOX_E_PDM_ERROR"> 8019 Controlled power off failed. 8020 </result> 8021 </desc> 8022 </method> 8023 8024 <method name="sleepButton"> 8025 <desc>Sends the ACPI sleep button event to the guest. 8026 <result name="VBOX_E_INVALID_VM_STATE"> 8027 Virtual machine not in Running state. 8028 </result> 8029 <result name="VBOX_E_PDM_ERROR"> 8030 Sending sleep button event failed. 8031 </result> 8032 </desc> 8033 </method> 8034 8035 <method name="getPowerButtonHandled"> 8036 <desc>Checks if the last power button event was handled by guest. 8037 <result name="VBOX_E_PDM_ERROR"> 8038 Checking if the event was handled by the guest OS failed. 8039 </result> 8040 </desc> 8041 <param name="handled" type="boolean" dir="return"/> 8042 </method> 8043 8044 <method name="getGuestEnteredACPIMode"> 8045 <desc>Checks if the guest entered the ACPI mode G0 (working) or 8046 G1 (sleeping). If this method returns @c false, the guest will 8047 most likely not respond to external ACPI events. 8048 <result name="VBOX_E_INVALID_VM_STATE"> 8049 Virtual machine not in Running state. 8050 </result> 8051 </desc> 8052 <param name="entered" type="boolean" dir="return"/> 8053 </method> 8054 8055 <method name="getDeviceActivity"> 8056 <desc> 8057 Gets the current activity type of given devices or device groups. 8058 <result name="E_INVALIDARG"> 8059 Invalid device type. 8060 </result> 8061 </desc> 8062 <param name="type" type="DeviceType" safearray="yes" dir="in"/> 8063 <param name="activity" type="DeviceActivity" safearray="yes" dir="return"/> 8064 </method> 8065 8066 <method name="attachUSBDevice"> 8067 <desc> 8068 Attaches a host USB device with the given UUID to the 8069 USB controller of the virtual machine. 8070 8071 The device needs to be in one of the following states: 8072 <link to="USBDeviceState_Busy"/>, 8073 <link to="USBDeviceState_Available"/> or 8074 <link to="USBDeviceState_Held"/>, 8075 otherwise an error is immediately returned. 8076 8077 When the device state is 8078 <link to="USBDeviceState_Busy">Busy</link>, an error may also 8079 be returned if the host computer refuses to release it for some reason. 8080 8081 <see><link to="IUSBDeviceFilters::deviceFilters"/>, 8082 <link to="USBDeviceState"/></see> 8083 <result name="VBOX_E_INVALID_VM_STATE"> 8084 Virtual machine state neither Running nor Paused. 8085 </result> 8086 <result name="VBOX_E_PDM_ERROR"> 8087 Virtual machine does not have a USB controller. 8088 </result> 8089 </desc> 8090 <param name="id" type="uuid" mod="string" dir="in"> 8091 <desc>UUID of the host USB device to attach.</desc> 8092 </param> 8093 <param name="captureFilename" type="wstring" dir="in"> 8094 <desc>Filename to capture the USB traffic to.</desc> 8095 </param> 8096 </method> 8097 8098 <method name="detachUSBDevice"> 8099 <desc> 8100 Detaches an USB device with the given UUID from the USB controller 8101 of the virtual machine. 8102 8103 After this method succeeds, the VirtualBox server re-initiates 8104 all USB filters as if the device were just physically attached 8105 to the host, but filters of this machine are ignored to avoid 8106 a possible automatic re-attachment. 8107 8108 <see><link to="IUSBDeviceFilters::deviceFilters"/>, 8109 <link to="USBDeviceState"/></see> 8110 8111 <result name="VBOX_E_PDM_ERROR"> 8112 Virtual machine does not have a USB controller. 8113 </result> 8114 <result name="E_INVALIDARG"> 8115 USB device not attached to this virtual machine. 8116 </result> 8117 </desc> 8118 <param name="id" type="uuid" mod="string" dir="in"> 8119 <desc>UUID of the USB device to detach.</desc> 8120 </param> 8121 <param name="device" type="IUSBDevice" dir="return"> 8122 <desc>Detached USB device.</desc> 8123 </param> 8124 </method> 8125 8126 <method name="findUSBDeviceByAddress"> 8127 <desc> 8128 Searches for a USB device with the given host address. 8129 8130 <result name="VBOX_E_OBJECT_NOT_FOUND"> 8131 Given @c name does not correspond to any USB device. 8132 </result> 8133 8134 <see><link to="IUSBDevice::address"/></see> 8135 </desc> 8136 <param name="name" type="wstring" dir="in"> 8137 <desc> 8138 Address of the USB device (as assigned by the host) to 8139 search for. 8140 </desc> 8141 </param> 8142 <param name="device" type="IUSBDevice" dir="return"> 8143 <desc>Found USB device object.</desc> 8144 </param> 8145 </method> 8146 8147 <method name="findUSBDeviceById"> 8148 <desc> 8149 Searches for a USB device with the given UUID. 8150 8151 <result name="VBOX_E_OBJECT_NOT_FOUND"> 8152 Given @c id does not correspond to any USB device. 8153 </result> 8154 8155 <see><link to="IUSBDevice::id"/></see> 8156 </desc> 8157 <param name="id" type="uuid" mod="string" dir="in"> 8158 <desc>UUID of the USB device to search for.</desc> 8159 </param> 8160 <param name="device" type="IUSBDevice" dir="return"> 8161 <desc>Found USB device object.</desc> 8162 </param> 8163 </method> 8164 8165 <method name="createSharedFolder"> 8166 <desc> 8167 Creates a transient new shared folder by associating the given logical 8168 name with the given host path, adds it to the collection of shared 8169 folders and starts sharing it. Refer to the description of 8170 <link to="ISharedFolder"/> to read more about logical names. 8171 8172 <result name="VBOX_E_INVALID_VM_STATE"> 8173 Virtual machine in Saved state or currently changing state. 8174 </result> 8175 <result name="VBOX_E_FILE_ERROR"> 8176 Shared folder already exists or not accessible. 8177 </result> 8178 </desc> 8179 <param name="name" type="wstring" dir="in"> 8180 <desc>Unique logical name of the shared folder.</desc> 8181 </param> 8182 <param name="hostPath" type="wstring" dir="in"> 8183 <desc>Full path to the shared folder in the host file system.</desc> 8184 </param> 8185 <param name="writable" type="boolean" dir="in"> 8186 <desc>Whether the share is writable or readonly</desc> 8187 </param> 8188 <param name="automount" type="boolean" dir="in"> 8189 <desc>Whether the share gets automatically mounted by the guest 8190 or not.</desc> 8191 </param> 8192 </method> 8193 8194 <method name="removeSharedFolder"> 8195 <desc> 8196 Removes a transient shared folder with the given name previously 8197 created by <link to="#createSharedFolder"/> from the collection of 8198 shared folders and stops sharing it. 8199 <result name="VBOX_E_INVALID_VM_STATE"> 8200 Virtual machine in Saved state or currently changing state. 8201 </result> 8202 <result name="VBOX_E_FILE_ERROR"> 8203 Shared folder does not exists. 8204 </result> 8205 </desc> 8206 <param name="name" type="wstring" dir="in"> 8207 <desc>Logical name of the shared folder to remove.</desc> 8368 8208 </param> 8369 8209 </method> … … 12986 12826 12987 12827 The ISnapshot interface has no methods, only attributes; snapshots 12988 are controlled through methods of the <link to="I Console" /> interface12828 are controlled through methods of the <link to="IMachine" /> interface 12989 12829 which also manage the media associated with the snapshot. 12990 12830 The following operations exist: 12991 12831 12992 12832 <ul> 12993 <li><link to="I Console::takeSnapshot"/> creates a new snapshot12833 <li><link to="IMachine::takeSnapshot"/> creates a new snapshot 12994 12834 by creating new, empty differencing images for the machine's 12995 12835 media and saving the VM settings and (if the VM is running) … … 18192 18032 <desc>Host is running low on battery (power management event).</desc> 18193 18033 </const> 18034 <const name="Snapshot" value="4"> 18035 <desc>A snapshot of the VM is being taken.</desc> 18036 </const> 18194 18037 </enum> 18195 18038 18196 18039 <interface 18197 18040 name="IInternalSessionControl" extends="$unknown" 18198 uuid=" fdb5fa71-eddb-4e06-9844-277d22270fe0"18041 uuid="747e397e-69c8-45a0-88d9-f7f070960718" 18199 18042 internal="yes" 18200 18043 wsmap="suppress" 18201 18044 > 18202 < method name="getPID">18045 <attribute name="PID" type="unsigned long" readonly="yes"> 18203 18046 <desc>PID of the process that has created this Session object. 18204 18047 </desc> 18205 <param name="pid" type="unsigned long" dir="return"/> 18206 </method> 18207 18208 <method name="getRemoteConsole"> 18048 </attribute> 18049 18050 <attribute name="remoteConsole" type="IConsole" readonly="yes"> 18209 18051 <desc> 18210 18052 Returns the console object suitable for remote control. … … 18218 18060 18219 18061 </desc> 18220 <param name="console" type="IConsole" dir="return"/> 18221 </method> 18062 </attribute> 18063 18064 <attribute name="nominalState" type="MachineState" readonly="yes"> 18065 <desc>Returns suitable machine state for the VM execution state. Useful 18066 for choosing a sensible machine state after a complex operation which 18067 failed or otherwise resulted in an unclear situation. 18068 </desc> 18069 </attribute> 18222 18070 18223 18071 <if target="midl"> … … 18688 18536 </method> 18689 18537 18538 <method name="reconfigureMediumAttachments"> 18539 <desc> 18540 Reconfigure all specified medium attachments in one go, making sure 18541 the current state corresponds to the specified medium. 18542 18543 <result name="VBOX_E_INVALID_VM_STATE"> 18544 Machine session is not open. 18545 </result> 18546 <result name="VBOX_E_INVALID_OBJECT_STATE"> 18547 Session type is not direct. 18548 </result> 18549 </desc> 18550 <param name="attachments" type="IMediumAttachment" dir="in" safearray="yes"> 18551 <desc>Array containing the medium attachments which need to be 18552 reconfigured.</desc> 18553 </param> 18554 </method> 18555 18690 18556 <method name="enableVMMStatistics"> 18691 18557 <desc> … … 18751 18617 might behave slightly differently than a normal VM save state. 18752 18618 18619 This call is fully synchronous, and the caller is expected to have set 18620 the machine state appropriately (and has to set the follow-up machine 18621 state if this call failed). 18622 18753 18623 <result name="VBOX_E_INVALID_VM_STATE"> 18754 Virtual machine state neither Running nor Paused.18624 Virtual machine state is not one of the expected values. 18755 18625 </result> 18756 18626 <result name="VBOX_E_FILE_ERROR"> 18757 18627 Failed to create directory for saved state file. 18758 18628 </result> 18759 <see><link to="I Console::saveState"/></see>18629 <see><link to="IMachine::saveState"/></see> 18760 18630 </desc> 18761 18631 … … 18763 18633 <desc>Specify the best matching reason code please.</desc> 18764 18634 </param> 18765 <param name="progress" type="IProgress" dir=" return">18635 <param name="progress" type="IProgress" dir="in"> 18766 18636 <desc>Progress object to track the operation completion.</desc> 18767 18637 </param> 18638 <param name="stateFilePath" type="wstring" dir="in"> 18639 <desc>File path the VM process must save the execution state to.</desc> 18640 </param> 18641 <param name="pauseVM" type="boolean" dir="in"> 18642 <desc>The VM should be paused before saving state. It is automatically 18643 unpaused on error in the "vanilla save state" case.</desc> 18644 </param> 18645 <param name="leftPaused" type="boolean" dir="return"> 18646 <desc>Returns if the VM was left in paused state, which is necessary 18647 in many situations (snapshots, teleportation).</desc> 18648 </param> 18649 </method> 18650 18651 <method name="cancelSaveStateWithReason"> 18652 <desc> 18653 Internal method for cancelling a VM save state. 18654 <see><link to="IInternalSessionControl::saveStateWithReason"/></see> 18655 </desc> 18768 18656 </method> 18769 18657 -
trunk/src/VBox/Main/include/ConsoleImpl.h
r55184 r55214 155 155 156 156 HRESULT i_updateMachineState(MachineState_T aMachineState); 157 HRESULT i_getNominalState(MachineState_T &aNominalState); 157 158 158 159 // events from IInternalSessionControl … … 188 189 ULONG aSourceIdx, ULONG aTargetIdx, 189 190 IProgress *aProgress); 191 HRESULT i_reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments); 190 192 int i_hgcmLoadService(const char *pszServiceLibrary, const char *pszServiceName); 191 193 VMMDev *i_getVMMDev() { return m_pVMMDev; } … … 230 232 231 233 HRESULT i_pause(Reason_T aReason); 232 HRESULT i_resume(Reason_T aReason); 233 HRESULT i_saveState(Reason_T aReason, IProgress **aProgress); 234 HRESULT i_resume(Reason_T aReason, AutoWriteLock &alock); 235 HRESULT i_saveState(Reason_T aReason, const ComPtr<IProgress> &aProgress, const Utf8Str &aStateFilePath, bool fPauseVM, bool &fLeftPaused); 236 HRESULT i_cancelSaveState(); 234 237 235 238 // callback callers (partly; for some events console callbacks are notified … … 318 321 HRESULT getPowerButtonHandled(BOOL *aHandled); 319 322 HRESULT getGuestEnteredACPIMode(BOOL *aEntered); 320 HRESULT saveState(ComPtr<IProgress> &aProgress);321 HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);322 HRESULT discardSavedState(BOOL aFRemoveFile);323 323 HRESULT getDeviceActivity(const std::vector<DeviceType_T> &aType, 324 324 std::vector<DeviceActivity_T> &aActivity); … … 335 335 BOOL aAutomount); 336 336 HRESULT removeSharedFolder(const com::Utf8Str &aName); 337 HRESULT takeSnapshot(const com::Utf8Str &aName,338 const com::Utf8Str &aDescription,339 ComPtr<IProgress> &aProgress);340 HRESULT deleteSnapshot(const com::Guid &aId,341 ComPtr<IProgress> &aProgress);342 HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId,343 ComPtr<IProgress> &aProgress);344 HRESULT deleteSnapshotRange(const com::Guid &aStartId,345 const com::Guid &aEndId,346 ComPtr<IProgress> &aProgress);347 HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot,348 ComPtr<IProgress> &aProgress);349 337 HRESULT teleport(const com::Utf8Str &aHostname, 350 338 ULONG aTcpport, … … 751 739 HRESULT i_doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PUVM pUVM, bool fSilent); 752 740 753 static DECLCALLBACK(int) i_fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser);754 755 741 static DECLCALLBACK(int) i_stateProgressCallback(PUVM pUVM, unsigned uPercent, void *pvUser); 756 742 … … 766 752 767 753 static DECLCALLBACK(int) i_powerUpThread(RTTHREAD Thread, void *pvUser); 768 static DECLCALLBACK(int) i_saveStateThread(RTTHREAD Thread, void *pvUser);769 754 static DECLCALLBACK(int) i_powerDownThread(RTTHREAD Thread, void *pvUser); 770 755 … … 997 982 * teleportation operation, will cancel the teleportation / live snapshot 998 983 * operation before starting. */ 999 Com ObjPtr<Progress> mptrCancelableProgress;984 ComPtr<IProgress> mptrCancelableProgress; 1000 985 1001 986 ComPtr<IEventListener> mVmListener; -
trunk/src/VBox/Main/include/Global.h
r49074 r55214 97 97 * dedicated process) or not. Note that some online states are also 98 98 * transitional states (see #IsTransitional()). 99 *100 * @remarks Saving may actually be an offline state according to the101 * documentation (offline snapshot).102 99 */ 103 100 static bool IsOnline(MachineState_T aState) 104 101 { 105 #if 0106 102 return aState >= MachineState_FirstOnline && 107 103 aState <= MachineState_LastOnline; 108 #else109 switch (aState)110 {111 case MachineState_Running:112 case MachineState_Paused:113 case MachineState_Teleporting:114 case MachineState_LiveSnapshotting:115 case MachineState_Stuck:116 case MachineState_Starting:117 case MachineState_Stopping:118 case MachineState_Saving:119 case MachineState_Restoring:120 case MachineState_TeleportingPausedVM:121 case MachineState_TeleportingIn:122 return true;123 default:124 return false;125 }126 #endif127 104 } 128 105 … … 136 113 static bool IsTransient(MachineState_T aState) 137 114 { 138 #if 0139 115 return aState >= MachineState_FirstTransient && 140 116 aState <= MachineState_LastTransient; 141 #else142 switch (aState)143 {144 case MachineState_Teleporting:145 case MachineState_LiveSnapshotting:146 case MachineState_Starting:147 case MachineState_Stopping:148 case MachineState_Saving:149 case MachineState_Restoring:150 case MachineState_TeleportingPausedVM:151 case MachineState_TeleportingIn:152 case MachineState_RestoringSnapshot:153 case MachineState_DeletingSnapshot:154 case MachineState_SettingUp:155 return true;156 default:157 return false;158 }159 #endif160 117 } 161 118 -
trunk/src/VBox/Main/include/MachineImpl.h
r55168 r55214 125 125 struct Session 126 126 { 127 /** Type of lock which created this session */ 128 LockType_T mLockType; 129 127 130 /** Control of the direct session opened by lockMachine() */ 128 131 ComPtr<IInternalSessionControl> mDirectControl; … … 597 600 } 598 601 599 602 static HRESULT i_setErrorStatic(HRESULT aResultCode, const char *pcszMsg, ...); 600 603 601 604 protected: … … 712 715 bool i_isControllerHotplugCapable(StorageControllerType_T enmCtrlType); 713 716 714 struct DeleteTask;715 static DECLCALLBACK(int) deleteThread(RTTHREAD Thread, void *pvUser);716 HRESULT i_deleteTaskWorker(DeleteTask &task);717 717 Utf8Str i_getExtraData(const Utf8Str &strKey); 718 718 … … 778 778 779 779 uint64_t uRegistryNeedsSaving; 780 781 /** 782 * Abstract base class for all Machine or SessionMachine related 783 * asynchronous tasks. This is necessary since RTThreadCreate cannot call 784 * a (non-static) method as its thread function, so instead we have it call 785 * the static Machine::taskHandler, which then calls the handler() method 786 * in here (implemented by the subclasses). 787 */ 788 struct Task 789 { 790 Task(Machine *m, Progress *p, const Utf8Str &t) 791 : m_pMachine(m), 792 m_machineCaller(m), 793 m_pProgress(p), 794 m_strTaskName(t), 795 m_machineStateBackup(m->mData->mMachineState) // save the current machine state 796 {} 797 798 HRESULT createThread() 799 { 800 int vrc = RTThreadCreate(NULL, 801 taskHandler, 802 (void *)this, 803 0, 804 RTTHREADTYPE_MAIN_WORKER, 805 0, 806 m_strTaskName.c_str()); 807 if (RT_FAILURE(vrc)) 808 { 809 HRESULT rc = Machine::i_setErrorStatic(E_FAIL, Machine::tr("Could not create thread \"%s\" (%Rrc)"), m_strTaskName.c_str(), vrc); 810 delete this; 811 return rc; 812 } 813 return S_OK; 814 } 815 816 void modifyBackedUpState(MachineState_T s) 817 { 818 *const_cast<MachineState_T *>(&m_machineStateBackup) = s; 819 } 820 821 virtual void handler() = 0; 822 823 ComObjPtr<Machine> m_pMachine; 824 AutoCaller m_machineCaller; 825 ComObjPtr<Progress> m_pProgress; 826 Utf8Str m_strTaskName; 827 const MachineState_T m_machineStateBackup; 828 }; 829 830 struct DeleteConfigTask; 831 void i_deleteConfigHandler(DeleteConfigTask &task); 832 833 static DECLCALLBACK(int) taskHandler(RTTHREAD thread, void *pvUser); 780 834 781 835 friend class SessionMachine; … … 1131 1185 const std::vector<CloneOptions_T> &aOptions, 1132 1186 ComPtr<IProgress> &aProgress); 1187 HRESULT saveState(ComPtr<IProgress> &aProgress); 1188 HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile); 1189 HRESULT discardSavedState(BOOL aFRemoveFile); 1190 HRESULT takeSnapshot(const com::Utf8Str &aName, 1191 const com::Utf8Str &aDescription, 1192 BOOL aPause, 1193 ComPtr<IProgress> &aProgress); 1194 HRESULT deleteSnapshot(const com::Guid &aId, 1195 ComPtr<IProgress> &aProgress); 1196 HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId, 1197 ComPtr<IProgress> &aProgress); 1198 HRESULT deleteSnapshotRange(const com::Guid &aStartId, 1199 const com::Guid &aEndId, 1200 ComPtr<IProgress> &aProgress); 1201 HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, 1202 ComPtr<IProgress> &aProgress); 1133 1203 1134 1204 // wrapped IInternalMachineControl properties 1135 1205 1136 1206 // wrapped IInternalMachineControl methods 1137 HRESULT setRemoveSavedStateFile(BOOL aRemove);1138 1207 HRESULT updateState(MachineState_T aState); 1139 1208 HRESULT beginPowerUp(const ComPtr<IProgress> &aProgress); … … 1145 1214 BOOL *aMatched, 1146 1215 ULONG *aMaskedInterfaces); 1147 HRESULT captureUSBDevice(const com::Guid &aId, const com::Utf8Str &aCaptureFilename); 1216 HRESULT captureUSBDevice(const com::Guid &aId, 1217 const com::Utf8Str &aCaptureFilename); 1148 1218 HRESULT detachUSBDevice(const com::Guid &aId, 1149 1219 BOOL aDone); … … 1152 1222 HRESULT onSessionEnd(const ComPtr<ISession> &aSession, 1153 1223 ComPtr<IProgress> &aProgress); 1154 HRESULT beginSavingState(ComPtr<IProgress> &aProgress,1155 com::Utf8Str &aStateFilePath);1156 HRESULT endSavingState(LONG aResult,1157 const com::Utf8Str &aErrMsg);1158 HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);1159 HRESULT beginTakingSnapshot(const ComPtr<IConsole> &aInitiator,1160 const com::Utf8Str &aName,1161 const com::Utf8Str &aDescription,1162 const ComPtr<IProgress> &aConsoleProgress,1163 BOOL aFTakingSnapshotOnline,1164 com::Utf8Str &aStateFilePath);1165 HRESULT endTakingSnapshot(BOOL aSuccess);1166 HRESULT deleteSnapshot(const ComPtr<IConsole> &aInitiator,1167 const com::Guid &aStartId,1168 const com::Guid &aEndId,1169 BOOL aDeleteAllChildren,1170 MachineState_T *aMachineState,1171 ComPtr<IProgress> &aProgress);1172 1224 HRESULT finishOnlineMergeMedium(); 1173 HRESULT restoreSnapshot(const ComPtr<IConsole> &aInitiator,1174 const ComPtr<ISnapshot> &aSnapshot,1175 MachineState_T *aMachineState,1176 ComPtr<IProgress> &aProgress);1177 1225 HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames, 1178 1226 std::vector<com::Utf8Str> &aValues, … … 1203 1251 ULONG aVmNetRx, 1204 1252 ULONG aVmNetTx); 1205 1206 1207 1208 1209 1253 }; 1210 1254 … … 1302 1346 HRESULT i_unlockMedia(); 1303 1347 1348 HRESULT i_saveStateWithReason(Reason_T aReason, ComPtr<IProgress> &aProgress); 1349 1304 1350 private: 1305 1351 … … 1324 1370 HRESULT onSessionEnd(const ComPtr<ISession> &aSession, 1325 1371 ComPtr<IProgress> &aProgress); 1326 HRESULT beginSavingState(ComPtr<IProgress> &aProgress,1327 com::Utf8Str &aStateFilePath);1328 HRESULT endSavingState(LONG aResult,1329 const com::Utf8Str &aErrMsg);1330 HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);1331 HRESULT beginTakingSnapshot(const ComPtr<IConsole> &aInitiator,1332 const com::Utf8Str &aName,1333 const com::Utf8Str &aDescription,1334 const ComPtr<IProgress> &aConsoleProgress,1335 BOOL aFTakingSnapshotOnline,1336 com::Utf8Str &aStateFilePath);1337 HRESULT endTakingSnapshot(BOOL aSuccess);1338 HRESULT deleteSnapshot(const ComPtr<IConsole> &aInitiator,1339 const com::Guid &aStartId,1340 const com::Guid &aEndId,1341 BOOL aDeleteAllChildren,1342 MachineState_T *aMachineState,1343 ComPtr<IProgress> &aProgress);1344 1372 HRESULT finishOnlineMergeMedium(); 1345 HRESULT restoreSnapshot(const ComPtr<IConsole> &aInitiator,1346 const ComPtr<ISnapshot> &aSnapshot,1347 MachineState_T *aMachineState,1348 ComPtr<IProgress> &aProgress);1349 1373 HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames, 1350 1374 std::vector<com::Utf8Str> &aValues, … … 1380 1404 { 1381 1405 ConsoleTaskData() 1382 : mLastState(MachineState_Null), mDeleteSnapshotInfo(NULL) 1406 : mLastState(MachineState_Null), 1407 mDeleteSnapshotInfo(NULL) 1383 1408 { } 1384 1409 … … 1386 1411 ComObjPtr<Progress> mProgress; 1387 1412 1388 // used when taking snapshot 1389 ComObjPtr<Snapshot> mSnapshot; 1390 1391 // used when deleting online snapshot 1413 // used when deleting online snaphshot 1392 1414 void *mDeleteSnapshotInfo; 1393 1394 // used when saving state (either as part of a snapshot or separate)1395 Utf8Str strStateFilePath;1396 1415 }; 1397 1416 1417 struct SaveStateTask; 1398 1418 struct SnapshotTask; 1419 struct TakeSnapshotTask; 1399 1420 struct DeleteSnapshotTask; 1400 1421 struct RestoreSnapshotTask; 1401 1422 1423 friend struct TakeSnapshotTask; 1402 1424 friend struct DeleteSnapshotTask; 1403 1425 friend struct RestoreSnapshotTask; 1404 1426 1405 HRESULT i_endSavingState(HRESULT aRC, const Utf8Str &aErrMsg); 1427 void i_saveStateHandler(SaveStateTask &aTask); 1428 1429 // Override some functionality for SessionMachine, this is where the 1430 // real action happens (the Machine methods are just dummies). 1431 HRESULT saveState(ComPtr<IProgress> &aProgress); 1432 HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile); 1433 HRESULT discardSavedState(BOOL aFRemoveFile); 1434 HRESULT takeSnapshot(const com::Utf8Str &aName, 1435 const com::Utf8Str &aDescription, 1436 BOOL aPause, 1437 ComPtr<IProgress> &aProgress); 1438 HRESULT deleteSnapshot(const com::Guid &aId, 1439 ComPtr<IProgress> &aProgress); 1440 HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId, 1441 ComPtr<IProgress> &aProgress); 1442 HRESULT deleteSnapshotRange(const com::Guid &aStartId, 1443 const com::Guid &aEndId, 1444 ComPtr<IProgress> &aProgress); 1445 HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, 1446 ComPtr<IProgress> &aProgress); 1447 1406 1448 void i_releaseSavedStateFile(const Utf8Str &strSavedStateFile, Snapshot *pSnapshotToIgnore); 1407 1449 1450 void i_takeSnapshotHandler(TakeSnapshotTask &aTask); 1451 static void i_takeSnapshotProgressCancelCallback(void *pvUser); 1452 HRESULT i_finishTakingSnapshot(TakeSnapshotTask &aTask, AutoWriteLock &alock, bool aSuccess); 1453 HRESULT i_deleteSnapshot(const com::Guid &aStartId, 1454 const com::Guid &aEndId, 1455 BOOL aDeleteAllChildren, 1456 ComPtr<IProgress> &aProgress); 1408 1457 void i_deleteSnapshotHandler(DeleteSnapshotTask &aTask); 1409 1458 void i_restoreSnapshotHandler(RestoreSnapshotTask &aTask); … … 1451 1500 1452 1501 int miNATNetworksStarted; 1453 1454 static DECLCALLBACK(int) taskHandler(RTTHREAD thread, void *pvUser);1455 1502 }; 1456 1503 -
trunk/src/VBox/Main/include/SessionImpl.h
r53062 r55214 53 53 private: 54 54 55 // Wrapped I session properties55 // Wrapped ISession properties 56 56 HRESULT getState(SessionState_T *aState); 57 57 HRESULT getType(SessionType_T *aType); … … 59 59 HRESULT getConsole(ComPtr<IConsole> &aConsole); 60 60 61 // Wrapped I session methods61 // Wrapped ISession methods 62 62 HRESULT unlockMachine(); 63 64 // Wrapped IInternalSessionControl properties 63 65 HRESULT getPID(ULONG *aPid); 64 HRESULT getRemoteConsole(ComPtr<IConsole> &aConsole); 66 HRESULT getRemoteConsole(ComPtr<IConsole> &aRemoteConsole); 67 HRESULT getNominalState(MachineState_T *aNominalState); 68 69 // Wrapped IInternalSessionControl methods 65 70 #ifndef VBOX_WITH_GENERIC_SESSION_WATCHER 66 71 HRESULT assignMachine(const ComPtr<IMachine> &aMachine, … … 121 126 ULONG aTargetIdx, 122 127 const ComPtr<IProgress> &aProgress); 128 HRESULT reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments); 123 129 HRESULT enableVMMStatistics(BOOL aEnable); 124 130 HRESULT pauseWithReason(Reason_T aReason); 125 131 HRESULT resumeWithReason(Reason_T aReason); 126 132 HRESULT saveStateWithReason(Reason_T aReason, 127 ComPtr<IProgress> &aProgress); 128 HRESULT unlockMachine(bool aFinalRelease, bool aFromServer); 133 const ComPtr<IProgress> &aProgress, 134 const Utf8Str &aStateFilePath, 135 BOOL aPauseVM, 136 BOOL *aLeftPaused); 137 HRESULT cancelSaveStateWithReason(); 138 139 140 HRESULT i_unlockMachine(bool aFinalRelease, bool aFromServer); 129 141 130 142 SessionState_T mState; -
trunk/src/VBox/Main/src-all/Global.cpp
r54017 r55214 7 7 8 8 /* 9 * Copyright (C) 2008-201 3Oracle Corporation9 * Copyright (C) 2008-2015 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 448 448 case MachineState_DeletingSnapshotOnline: return "DeletingSnapshotOnline"; 449 449 case MachineState_DeletingSnapshotPaused: return "DeletingSnapshotPaused"; 450 case MachineState_OnlineSnapshotting: return "OnlineSnapshotting"; 450 451 case MachineState_RestoringSnapshot: return "RestoringSnapshot"; 451 452 case MachineState_DeletingSnapshot: return "DeletingSnapshot"; 452 453 case MachineState_SettingUp: return "SettingUp"; 454 case MachineState_Snapshotting: return "Snapshotting"; 453 455 default: 454 456 { … … 513 515 case Reason_HostResume: return "host resume"; 514 516 case Reason_HostBatteryLow: return "host battery low"; 517 case Reason_Snapshot: return "snapshot"; 515 518 default: 516 519 { -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r55185 r55214 164 164 mProgress(aProgress), 165 165 mServerProgress(aServerProgress), 166 mpUVM(NULL),167 166 mRC(E_FAIL), 168 167 mpSafeVMPtr(NULL) … … 175 174 { 176 175 mpSafeVMPtr = new Console::SafeVMPtr(aConsole); 177 if (mpSafeVMPtr->isOk()) 178 mpUVM = mpSafeVMPtr->rawUVM(); 179 else 176 if (!mpSafeVMPtr->isOk()) 180 177 mRC = mpSafeVMPtr->rc(); 181 178 } … … 205 202 Utf8Str mErrorMsg; 206 203 const ComPtr<IProgress> mServerProgress; 207 PUVM mpUVM;208 204 209 205 private: … … 212 208 }; 213 209 214 struct VMTakeSnapshotTask : public VMTask215 {216 VMTakeSnapshotTask(Console *aConsole,217 Progress *aProgress,218 IN_BSTR aName,219 IN_BSTR aDescription)220 : VMTask(aConsole, aProgress, NULL /* aServerProgress */,221 false /* aUsesVMPtr */),222 bstrName(aName),223 bstrDescription(aDescription),224 lastMachineState(MachineState_Null)225 {}226 227 Bstr bstrName,228 bstrDescription;229 Bstr bstrSavedStateFile; // received from BeginTakeSnapshot()230 MachineState_T lastMachineState;231 bool fTakingSnapshotOnline;232 ULONG ulMemSize;233 };234 210 235 211 struct VMPowerUpTask : public VMTask … … 264 240 true /* aUsesVMPtr */) 265 241 {} 266 };267 268 struct VMSaveTask : public VMTask269 {270 VMSaveTask(Console *aConsole,271 const ComPtr<IProgress> &aServerProgress,272 const Utf8Str &aSavedStateFile,273 MachineState_T aMachineStateBefore,274 Reason_T aReason)275 : VMTask(aConsole, NULL /* aProgress */, aServerProgress,276 true /* aUsesVMPtr */),277 mSavedStateFile(aSavedStateFile),278 mMachineStateBefore(aMachineStateBefore),279 mReason(aReason)280 {}281 282 Utf8Str mSavedStateFile;283 /* The local machine state we had before. Required if something fails */284 MachineState_T mMachineStateBefore;285 /* The reason for saving state */286 Reason_T mReason;287 242 }; 288 243 … … 597 552 meAttachmentType[slot] = NetworkAttachmentType_Null; 598 553 599 // VirtualBox 4.0: We no longer initialize the VMMDev instance here,600 // which starts the HGCM thread. Instead, this is now done in the601 // power-up thread when a VM is actually being powered up to avoid602 // having HGCM threads all over the place every time a session is603 // opened, even if that session will not run a VM.604 // unconst(m_pVMMDev) = new VMMDev(this);605 // AssertReturn(mVMMDev, E_FAIL);606 607 554 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 608 555 unconst(mAudioVRDE) = new AudioVRDE(this); … … 2106 2053 HRESULT Console::powerUp(ComPtr<IProgress> &aProgress) 2107 2054 { 2108 ComObjPtr<IProgress> pProgress; 2109 i_powerUp(pProgress.asOutParam(), false /* aPaused */); 2110 pProgress.queryInterfaceTo(aProgress.asOutParam()); 2055 i_powerUp(aProgress.asOutParam(), false /* aPaused */); 2111 2056 return S_OK; 2112 2057 } … … 2114 2059 HRESULT Console::powerUpPaused(ComPtr<IProgress> &aProgress) 2115 2060 { 2116 ComObjPtr<IProgress> pProgress; 2117 i_powerUp(pProgress.asOutParam(), true /* aPaused */); 2118 pProgress.queryInterfaceTo(aProgress.asOutParam()); 2061 i_powerUp(aProgress.asOutParam(), true /* aPaused */); 2119 2062 return S_OK; 2120 2063 } … … 2133 2076 case MachineState_Stuck: 2134 2077 break; 2078 2079 /* Try cancel the save state. */ 2080 case MachineState_Saving: 2081 if (!mptrCancelableProgress.isNull()) 2082 { 2083 HRESULT hrc = mptrCancelableProgress->Cancel(); 2084 if (SUCCEEDED(hrc)) 2085 break; 2086 } 2087 return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point during a save state")); 2135 2088 2136 2089 /* Try cancel the teleportation. */ … … 2145 2098 return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point in a teleportation")); 2146 2099 2100 /* Try cancel the online snapshot. */ 2101 case MachineState_OnlineSnapshotting: 2102 if (!mptrCancelableProgress.isNull()) 2103 { 2104 HRESULT hrc = mptrCancelableProgress->Cancel(); 2105 if (SUCCEEDED(hrc)) 2106 break; 2107 } 2108 return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point in an online snapshot")); 2109 2147 2110 /* Try cancel the live snapshot. */ 2148 2111 case MachineState_LiveSnapshotting: … … 2539 2502 LogFlowThisFuncEnter(); 2540 2503 2541 HRESULT rc = i_resume(Reason_Unspecified); 2504 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2505 2506 if (mMachineState != MachineState_Paused) 2507 return setError(VBOX_E_INVALID_VM_STATE, 2508 tr("Cannot resume the machine as it is not paused (machine state: %s)"), 2509 Global::stringifyMachineState(mMachineState)); 2510 2511 HRESULT rc = i_resume(Reason_Unspecified, alock); 2542 2512 2543 2513 LogFlowThisFunc(("rc=%Rhrc\n", rc)); … … 2720 2690 LogFlowThisFunc(("rc=%Rhrc\n", rc)); 2721 2691 LogFlowThisFuncLeave(); 2722 return rc;2723 }2724 2725 HRESULT Console::saveState(ComPtr<IProgress> &aProgress)2726 {2727 LogFlowThisFuncEnter();2728 ComObjPtr<IProgress> pProgress;2729 2730 HRESULT rc = i_saveState(Reason_Unspecified, pProgress.asOutParam());2731 pProgress.queryInterfaceTo(aProgress.asOutParam());2732 2733 LogFlowThisFunc(("rc=%Rhrc\n", rc));2734 LogFlowThisFuncLeave();2735 return rc;2736 }2737 2738 HRESULT Console::adoptSavedState(const com::Utf8Str &aSavedStateFile)2739 {2740 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);2741 2742 if ( mMachineState != MachineState_PoweredOff2743 && mMachineState != MachineState_Teleported2744 && mMachineState != MachineState_Aborted2745 )2746 return setError(VBOX_E_INVALID_VM_STATE,2747 tr("Cannot adopt the saved machine state as the machine is not in Powered Off, Teleported or Aborted state (machine state: %s)"),2748 Global::stringifyMachineState(mMachineState));2749 2750 return mControl->AdoptSavedState(Bstr(aSavedStateFile.c_str()).raw());2751 }2752 2753 HRESULT Console::discardSavedState(BOOL aFRemoveFile)2754 {2755 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);2756 2757 if (mMachineState != MachineState_Saved)2758 return setError(VBOX_E_INVALID_VM_STATE,2759 tr("Cannot delete the machine state as the machine is not in the saved state (machine state: %s)"),2760 Global::stringifyMachineState(mMachineState));2761 2762 HRESULT rc = mControl->SetRemoveSavedStateFile(aFRemoveFile);2763 if (FAILED(rc)) return rc;2764 2765 /*2766 * Saved -> PoweredOff transition will be detected in the SessionMachine2767 * and properly handled.2768 */2769 rc = i_setMachineState(MachineState_PoweredOff);2770 2771 2692 return rc; 2772 2693 } … … 3155 3076 3156 3077 return rc; 3157 }3158 3159 HRESULT Console::takeSnapshot(const com::Utf8Str &aName,3160 const com::Utf8Str &aDescription,3161 ComPtr<IProgress> &aProgress)3162 {3163 LogFlowThisFuncEnter();3164 3165 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);3166 LogFlowThisFunc(("aName='%s' mMachineState=%d\n", aName.c_str(), mMachineState));3167 3168 if (Global::IsTransient(mMachineState))3169 return setError(VBOX_E_INVALID_VM_STATE,3170 tr("Cannot take a snapshot of the machine while it is changing the state (machine state: %s)"),3171 Global::stringifyMachineState(mMachineState));3172 3173 HRESULT rc = S_OK;3174 3175 /* prepare the progress object:3176 a) count the no. of hard disk attachments to get a matching no. of progress sub-operations */3177 ULONG cOperations = 2; // always at least setting up + finishing up3178 ULONG ulTotalOperationsWeight = 2; // one each for setting up + finishing up3179 SafeIfaceArray<IMediumAttachment> aMediumAttachments;3180 rc = mMachine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aMediumAttachments));3181 if (FAILED(rc))3182 return setError(rc, tr("Cannot get medium attachments of the machine"));3183 3184 ULONG ulMemSize;3185 rc = mMachine->COMGETTER(MemorySize)(&ulMemSize);3186 if (FAILED(rc))3187 return rc;3188 3189 for (size_t i = 0;3190 i < aMediumAttachments.size();3191 ++i)3192 {3193 DeviceType_T type;3194 rc = aMediumAttachments[i]->COMGETTER(Type)(&type);3195 if (FAILED(rc))3196 return rc;3197 3198 if (type == DeviceType_HardDisk)3199 {3200 ++cOperations;3201 3202 // assume that creating a diff image takes as long as saving a 1MB state3203 // (note, the same value must be used in SessionMachine::BeginTakingSnapshot() on the server!)3204 ulTotalOperationsWeight += 1;3205 }3206 }3207 3208 // b) one extra sub-operations for online snapshots OR offline snapshots that have a saved state (needs to be copied)3209 bool const fTakingSnapshotOnline = Global::IsOnline(mMachineState);3210 3211 LogFlowFunc(("fTakingSnapshotOnline = %d, mMachineState = %d\n", fTakingSnapshotOnline, mMachineState));3212 3213 if (fTakingSnapshotOnline)3214 {3215 ++cOperations;3216 ulTotalOperationsWeight += ulMemSize;3217 }3218 3219 // finally, create the progress object3220 ComObjPtr<Progress> pProgress;3221 pProgress.createObject();3222 rc = pProgress->init(static_cast<IConsole *>(this),3223 Bstr(tr("Taking a snapshot of the virtual machine")).raw(),3224 (mMachineState >= MachineState_FirstOnline)3225 && (mMachineState <= MachineState_LastOnline) /* aCancelable */,3226 cOperations,3227 ulTotalOperationsWeight,3228 Bstr(tr("Setting up snapshot operation")).raw(), // first sub-op description3229 1); // ulFirstOperationWeight3230 3231 if (FAILED(rc))3232 return rc;3233 3234 VMTakeSnapshotTask *pTask;3235 if (!(pTask = new VMTakeSnapshotTask(this, pProgress, Bstr(aName).raw(), Bstr(aDescription).raw())))3236 return E_OUTOFMEMORY;3237 3238 Assert(pTask->mProgress);3239 3240 try3241 {3242 mptrCancelableProgress = pProgress;3243 3244 /*3245 * If we fail here it means a PowerDown() call happened on another3246 * thread while we were doing Pause() (which releases the Console lock).3247 * We assign PowerDown() a higher precedence than TakeSnapshot(),3248 * therefore just return the error to the caller.3249 */3250 rc = pTask->rc();3251 if (FAILED(rc)) throw rc;3252 3253 pTask->ulMemSize = ulMemSize;3254 3255 /* memorize the current machine state */3256 pTask->lastMachineState = mMachineState;3257 pTask->fTakingSnapshotOnline = fTakingSnapshotOnline;3258 3259 int vrc = RTThreadCreate(NULL,3260 Console::i_fntTakeSnapshotWorker,3261 (void *)pTask,3262 0,3263 RTTHREADTYPE_MAIN_WORKER,3264 0,3265 "TakeSnap");3266 if (FAILED(vrc))3267 throw setError(E_FAIL,3268 tr("Could not create VMTakeSnap thread (%Rrc)"),3269 vrc);3270 3271 pTask->mProgress.queryInterfaceTo(aProgress.asOutParam());3272 }3273 catch (HRESULT erc)3274 {3275 delete pTask;3276 rc = erc;3277 mptrCancelableProgress.setNull();3278 }3279 3280 LogFlowThisFunc(("rc=%Rhrc\n", rc));3281 LogFlowThisFuncLeave();3282 return rc;3283 }3284 3285 HRESULT Console::deleteSnapshot(const com::Guid &aId, ComPtr<IProgress> &aProgress)3286 {3287 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);3288 3289 if (Global::IsTransient(mMachineState))3290 return setError(VBOX_E_INVALID_VM_STATE,3291 tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),3292 Global::stringifyMachineState(mMachineState));3293 ComObjPtr<IProgress> iProgress;3294 MachineState_T machineState = MachineState_Null;3295 HRESULT rc = mControl->DeleteSnapshot((IConsole *)this, Bstr(aId.toString()).raw(), Bstr(aId.toString()).raw(),3296 FALSE /* fDeleteAllChildren */, &machineState, iProgress.asOutParam());3297 if (FAILED(rc)) return rc;3298 iProgress.queryInterfaceTo(aProgress.asOutParam());3299 3300 i_setMachineStateLocally(machineState);3301 return S_OK;3302 }3303 3304 HRESULT Console::deleteSnapshotAndAllChildren(const com::Guid &aId, ComPtr<IProgress> &aProgress)3305 3306 {3307 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);3308 3309 if (Global::IsTransient(mMachineState))3310 return setError(VBOX_E_INVALID_VM_STATE,3311 tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),3312 Global::stringifyMachineState(mMachineState));3313 3314 ComObjPtr<IProgress> iProgress;3315 MachineState_T machineState = MachineState_Null;3316 HRESULT rc = mControl->DeleteSnapshot((IConsole *)this, Bstr(aId.toString()).raw(), Bstr(aId.toString()).raw(),3317 TRUE /* fDeleteAllChildren */, &machineState, iProgress.asOutParam());3318 if (FAILED(rc)) return rc;3319 iProgress.queryInterfaceTo(aProgress.asOutParam());3320 3321 i_setMachineStateLocally(machineState);3322 return S_OK;3323 }3324 3325 HRESULT Console::deleteSnapshotRange(const com::Guid &aStartId, const com::Guid &aEndId, ComPtr<IProgress> &aProgress)3326 {3327 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);3328 3329 if (Global::IsTransient(mMachineState))3330 return setError(VBOX_E_INVALID_VM_STATE,3331 tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),3332 Global::stringifyMachineState(mMachineState));3333 3334 ComObjPtr<IProgress> iProgress;3335 MachineState_T machineState = MachineState_Null;3336 HRESULT rc = mControl->DeleteSnapshot((IConsole *)this, Bstr(aStartId.toString()).raw(), Bstr(aEndId.toString()).raw(),3337 FALSE /* fDeleteAllChildren */, &machineState, iProgress.asOutParam());3338 if (FAILED(rc)) return rc;3339 iProgress.queryInterfaceTo(aProgress.asOutParam());3340 3341 i_setMachineStateLocally(machineState);3342 return S_OK;3343 }3344 3345 HRESULT Console::restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, ComPtr<IProgress> &aProgress)3346 {3347 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);3348 3349 if (Global::IsOnlineOrTransient(mMachineState))3350 return setError(VBOX_E_INVALID_VM_STATE,3351 tr("Cannot delete the current state of the running machine (machine state: %s)"),3352 Global::stringifyMachineState(mMachineState));3353 3354 ISnapshot* iSnapshot = aSnapshot;3355 ComObjPtr<IProgress> iProgress;3356 MachineState_T machineState = MachineState_Null;3357 HRESULT rc = mControl->RestoreSnapshot((IConsole*)this, iSnapshot, &machineState, iProgress.asOutParam());3358 if (FAILED(rc)) return rc;3359 iProgress.queryInterfaceTo(aProgress.asOutParam());3360 3361 i_setMachineStateLocally(machineState);3362 return S_OK;3363 3078 } 3364 3079 … … 3645 3360 getStaticComponentName(), 3646 3361 Utf8StrFmt("Invalid state '%s' for changing medium", 3647 VMR3GetStateName(enmVMState)),3362 VMR3GetStateName(enmVMState)), 3648 3363 false /*aWarning*/, 3649 3364 true /*aLogIt*/); … … 6219 5934 6220 5935 /* We will need to release the lock before doing the actual merge */ 6221 Auto ReadLock alock(this COMMA_LOCKVAL_SRC_POS);5936 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 6222 5937 6223 5938 /* paranoia - we don't want merges to happen while teleporting etc. */ … … 6295 6010 AssertComRCReturnRC(rc); 6296 6011 6012 Assert(mMachineState == MachineState_DeletingSnapshotOnline); 6013 6014 /* Pause the VM, as it might have pending IO on this drive */ 6015 bool fResume = false; 6016 rc = i_suspendBeforeConfigChange(ptrVM.rawUVM(), &alock, &fResume); 6017 if (FAILED(rc)) 6018 return rc; 6019 6297 6020 alock.release(); 6298 6299 /* Pause the VM, as it might have pending IO on this drive */6300 VMSTATE enmVMState = VMR3GetStateU(ptrVM.rawUVM());6301 if (mMachineState == MachineState_DeletingSnapshotOnline)6302 {6303 LogFlowFunc(("Suspending the VM...\n"));6304 /* disable the callback to prevent Console-level state change */6305 mVMStateChangeCallbackDisabled = true;6306 int vrc2 = VMR3Suspend(ptrVM.rawUVM(), VMSUSPENDREASON_RECONFIG);6307 mVMStateChangeCallbackDisabled = false;6308 AssertRCReturn(vrc2, E_FAIL);6309 }6310 6311 6021 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, 6312 6022 (PFNRT)i_reconfigureMediumAttachment, 13, … … 6316 6026 /* error handling is after resuming the VM */ 6317 6027 6318 if (mMachineState == MachineState_DeletingSnapshotOnline) 6319 { 6320 LogFlowFunc(("Resuming the VM...\n")); 6321 /* disable the callback to prevent Console-level state change */ 6322 mVMStateChangeCallbackDisabled = true; 6323 int vrc2 = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG); 6324 mVMStateChangeCallbackDisabled = false; 6325 if (RT_FAILURE(vrc2)) 6326 { 6327 /* too bad, we failed. try to sync the console state with the VMM state */ 6328 AssertLogRelRC(vrc2); 6329 i_vmstateChangeCallback(ptrVM.rawUVM(), VMSTATE_SUSPENDED, enmVMState, this); 6330 } 6331 } 6028 if (fResume) 6029 i_resumeAfterConfigChange(ptrVM.rawUVM()); 6332 6030 6333 6031 if (RT_FAILURE(vrc)) … … 6356 6054 return setError(E_FAIL, tr("Failed to perform an online medium merge (%Rrc)"), vrc); 6357 6055 6056 alock.acquire(); 6358 6057 /* Pause the VM, as it might have pending IO on this drive */ 6359 enmVMState = VMR3GetStateU(ptrVM.rawUVM()); 6360 if (mMachineState == MachineState_DeletingSnapshotOnline) 6361 { 6362 LogFlowFunc(("Suspending the VM...\n")); 6363 /* disable the callback to prevent Console-level state change */ 6364 mVMStateChangeCallbackDisabled = true; 6365 int vrc2 = VMR3Suspend(ptrVM.rawUVM(), VMSUSPENDREASON_RECONFIG); 6366 mVMStateChangeCallbackDisabled = false; 6367 AssertRCReturn(vrc2, E_FAIL); 6368 } 6058 rc = i_suspendBeforeConfigChange(ptrVM.rawUVM(), &alock, &fResume); 6059 if (FAILED(rc)) 6060 return rc; 6061 alock.release(); 6369 6062 6370 6063 /* Update medium chain and state now, so that the VM can continue. */ … … 6378 6071 /* error handling is after resuming the VM */ 6379 6072 6380 if (mMachineState == MachineState_DeletingSnapshotOnline) 6381 { 6382 LogFlowFunc(("Resuming the VM...\n")); 6383 /* disable the callback to prevent Console-level state change */ 6384 mVMStateChangeCallbackDisabled = true; 6385 int vrc2 = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG); 6386 mVMStateChangeCallbackDisabled = false; 6387 AssertRC(vrc2); 6388 if (RT_FAILURE(vrc2)) 6389 { 6390 /* too bad, we failed. try to sync the console state with the VMM state */ 6391 i_vmstateChangeCallback(ptrVM.rawUVM(), VMSTATE_SUSPENDED, enmVMState, this); 6392 } 6393 } 6073 if (fResume) 6074 i_resumeAfterConfigChange(ptrVM.rawUVM()); 6394 6075 6395 6076 if (RT_FAILURE(vrc)) … … 6397 6078 if (FAILED(rc)) 6398 6079 return rc; 6080 6081 return rc; 6082 } 6083 6084 HRESULT Console::i_reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments) 6085 { 6086 HRESULT rc = S_OK; 6087 6088 AutoCaller autoCaller(this); 6089 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 6090 6091 /* get the VM handle. */ 6092 SafeVMPtr ptrVM(this); 6093 if (!ptrVM.isOk()) 6094 return ptrVM.rc(); 6095 6096 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 6097 6098 for (size_t i = 0; i < aAttachments.size(); ++i) 6099 { 6100 ComPtr<IStorageController> pStorageController; 6101 Bstr controllerName; 6102 ULONG lInstance; 6103 StorageControllerType_T enmController; 6104 StorageBus_T enmBus; 6105 BOOL fUseHostIOCache; 6106 6107 /* 6108 * We could pass the objects, but then EMT would have to do lots of 6109 * IPC (to VBoxSVC) which takes a significant amount of time. 6110 * Better query needed values here and pass them. 6111 */ 6112 rc = aAttachments[i]->COMGETTER(Controller)(controllerName.asOutParam()); 6113 if (FAILED(rc)) 6114 throw rc; 6115 6116 rc = mMachine->GetStorageControllerByName(controllerName.raw(), 6117 pStorageController.asOutParam()); 6118 if (FAILED(rc)) 6119 throw rc; 6120 6121 rc = pStorageController->COMGETTER(ControllerType)(&enmController); 6122 if (FAILED(rc)) 6123 throw rc; 6124 rc = pStorageController->COMGETTER(Instance)(&lInstance); 6125 if (FAILED(rc)) 6126 throw rc; 6127 rc = pStorageController->COMGETTER(Bus)(&enmBus); 6128 if (FAILED(rc)) 6129 throw rc; 6130 rc = pStorageController->COMGETTER(UseHostIOCache)(&fUseHostIOCache); 6131 if (FAILED(rc)) 6132 throw rc; 6133 6134 const char *pcszDevice = i_convertControllerTypeToDev(enmController); 6135 6136 BOOL fBuiltinIOCache; 6137 rc = mMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache); 6138 if (FAILED(rc)) 6139 throw rc; 6140 6141 alock.release(); 6142 6143 int vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, 6144 (PFNRT)i_reconfigureMediumAttachment, 13, 6145 this, ptrVM.rawUVM(), pcszDevice, lInstance, enmBus, fUseHostIOCache, 6146 fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */, 6147 0 /* uMergeTarget */, aAttachments[i], mMachineState, &rc); 6148 if (RT_FAILURE(vrc)) 6149 throw setError(E_FAIL, tr("%Rrc"), vrc); 6150 if (FAILED(rc)) 6151 throw rc; 6152 6153 alock.acquire(); 6154 } 6399 6155 6400 6156 return rc; … … 6450 6206 case MachineState_Paused: 6451 6207 case MachineState_TeleportingPausedVM: 6452 case MachineState_ Saving:6208 case MachineState_OnlineSnapshotting: 6453 6209 6454 6210 /* Remove any keys which are supposed to be removed on a suspend. */ … … 6502 6258 * a specific reason. 6503 6259 */ 6504 HRESULT Console::i_resume(Reason_T aReason )6260 HRESULT Console::i_resume(Reason_T aReason, AutoWriteLock &alock) 6505 6261 { 6506 6262 LogFlowThisFuncEnter(); … … 6508 6264 AutoCaller autoCaller(this); 6509 6265 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 6510 6511 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);6512 6513 if (mMachineState != MachineState_Paused)6514 return setError(VBOX_E_INVALID_VM_STATE,6515 tr("Cannot resume the machine as it is not paused (machine state: %s)"),6516 Global::stringifyMachineState(mMachineState));6517 6266 6518 6267 /* get the VM handle. */ … … 6544 6293 if (aReason == Reason_HostResume) 6545 6294 enmReason = VMRESUMEREASON_HOST_RESUME; 6295 else if (aReason == Reason_Snapshot) 6296 enmReason = VMRESUMEREASON_STATE_SAVED; 6297 6298 // for snapshots: no state change callback, VBoxSVC does everything 6299 if (aReason == Reason_Snapshot) 6300 mVMStateChangeCallbackDisabled = true; 6546 6301 vrc = VMR3Resume(ptrVM.rawUVM(), enmReason); 6302 if (aReason == Reason_Snapshot) 6303 mVMStateChangeCallbackDisabled = false; 6547 6304 } 6548 6305 … … 6558 6315 6559 6316 /** 6560 * Worker for Console::SaveState and internal entry point for saving state of 6561 * a VM for a specific reason. 6562 */ 6563 HRESULT Console::i_saveState(Reason_T aReason, IProgress **aProgress) 6317 * Internal entry point for saving state of a VM for a specific reason. This 6318 * method is completely synchronous. 6319 * 6320 * The machine state is already set appropriately. It is only changed when 6321 * saving state actually paused the VM (happens with live snapshots and 6322 * teleportation), and in this case reflects the now paused variant. 6323 * 6324 * @note Locks this object for writing. 6325 */ 6326 HRESULT Console::i_saveState(Reason_T aReason, const ComPtr<IProgress> &aProgress, const Utf8Str &aStateFilePath, bool aPauseVM, bool &aLeftPaused) 6564 6327 { 6565 6328 LogFlowThisFuncEnter(); 6566 6567 CheckComArgOutPointerValid(aProgress); 6329 aLeftPaused = false; 6330 6331 AssertReturn(!aProgress.isNull(), E_INVALIDARG); 6332 AssertReturn(!aStateFilePath.isEmpty(), E_INVALIDARG); 6568 6333 6569 6334 AutoCaller autoCaller(this); … … 6573 6338 6574 6339 LogFlowThisFunc(("mMachineState=%d\n", mMachineState)); 6575 if ( mMachineState != MachineState_Running 6576 && mMachineState != MachineState_Paused) 6340 if ( mMachineState != MachineState_Saving 6341 && mMachineState != MachineState_LiveSnapshotting 6342 && mMachineState != MachineState_OnlineSnapshotting 6343 && mMachineState != MachineState_Teleporting 6344 && mMachineState != MachineState_TeleportingPausedVM) 6577 6345 { 6578 6346 return setError(VBOX_E_INVALID_VM_STATE, … … 6580 6348 Global::stringifyMachineState(mMachineState)); 6581 6349 } 6350 bool fContinueAfterwards = mMachineState != MachineState_Saving; 6582 6351 6583 6352 Bstr strDisableSaveState; … … 6590 6359 LogRel(("Saving state of VM, reason \"%s\"\n", Global::stringifyReason(aReason))); 6591 6360 6592 /* memorize the current machine state */ 6593 MachineState_T lastMachineState = mMachineState; 6594 6595 if (mMachineState == MachineState_Running) 6596 { 6597 /* get the VM handle. */ 6598 SafeVMPtr ptrVM(this); 6599 if (!ptrVM.isOk()) 6600 return ptrVM.rc(); 6601 6361 /* ensure the directory for the saved state file exists */ 6362 { 6363 Utf8Str dir = aStateFilePath; 6364 dir.stripFilename(); 6365 if (!RTDirExists(dir.c_str())) 6366 { 6367 int vrc = RTDirCreateFullPath(dir.c_str(), 0700); 6368 if (RT_FAILURE(vrc)) 6369 return setError(VBOX_E_FILE_ERROR, 6370 tr("Could not create a directory '%s' to save the state to (%Rrc)"), 6371 dir.c_str(), vrc); 6372 } 6373 } 6374 6375 /* Get the VM handle early, we need it in several places. */ 6376 SafeVMPtr ptrVM(this); 6377 if (!ptrVM.isOk()) 6378 return ptrVM.rc(); 6379 6380 bool fPaused = false; 6381 if (aPauseVM) 6382 { 6602 6383 /* release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */ 6603 6384 alock.release(); … … 6610 6391 alock.acquire(); 6611 6392 6612 HRESULT hrc = S_OK;6613 6393 if (RT_FAILURE(vrc)) 6614 hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc); 6615 if (FAILED(hrc)) 6616 return hrc; 6617 } 6618 6619 HRESULT rc = S_OK; 6620 bool fBeganSavingState = false; 6621 bool fTaskCreationFailed = false; 6622 6623 do 6624 { 6625 ComPtr<IProgress> pProgress; 6626 Bstr stateFilePath; 6627 6394 return setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc); 6395 fPaused = true; 6396 } 6397 6398 LogFlowFunc(("Saving the state to '%s'...\n", aStateFilePath.c_str())); 6399 6400 mptrCancelableProgress = aProgress; 6401 alock.release(); 6402 int vrc = VMR3Save(ptrVM.rawUVM(), 6403 aStateFilePath.c_str(), 6404 fContinueAfterwards, 6405 Console::i_stateProgressCallback, 6406 static_cast<IProgress *>(aProgress), 6407 &aLeftPaused); 6408 alock.acquire(); 6409 mptrCancelableProgress.setNull(); 6410 if (RT_FAILURE(vrc)) 6411 { 6412 if (fPaused) 6413 { 6414 alock.release(); 6415 VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_RESTORED); 6416 alock.acquire(); 6417 } 6418 return setError(E_FAIL, tr("Failed to save the machine state to '%s' (%Rrc)"), 6419 aStateFilePath.c_str(), vrc); 6420 } 6421 Assert(fContinueAfterwards || !aLeftPaused); 6422 6423 if (!fContinueAfterwards) 6424 { 6628 6425 /* 6629 * request a saved state file path from the server6630 * ( this will set the machine state to Saving on the server to block6631 * others from accessing this machine)6426 * The machine has been successfully saved, so power it down 6427 * (vmstateChangeCallback() will set state to Saved on success). 6428 * Note: we release the VM caller, otherwise it will deadlock. 6632 6429 */ 6633 rc = mControl->BeginSavingState(pProgress.asOutParam(), 6634 stateFilePath.asOutParam()); 6635 if (FAILED(rc)) 6636 break; 6637 6638 fBeganSavingState = true; 6639 6640 /* sync the state with the server */ 6641 i_setMachineStateLocally(MachineState_Saving); 6642 6643 /* ensure the directory for the saved state file exists */ 6644 { 6645 Utf8Str dir = stateFilePath; 6646 dir.stripFilename(); 6647 if (!RTDirExists(dir.c_str())) 6648 { 6649 int vrc = RTDirCreateFullPath(dir.c_str(), 0700); 6650 if (RT_FAILURE(vrc)) 6651 { 6652 rc = setError(VBOX_E_FILE_ERROR, 6653 tr("Could not create a directory '%s' to save the state to (%Rrc)"), 6654 dir.c_str(), vrc); 6655 break; 6656 } 6657 } 6658 } 6659 6660 /* Create a task object early to ensure mpUVM protection is successful. */ 6661 std::auto_ptr<VMSaveTask> task(new VMSaveTask(this, pProgress, 6662 stateFilePath, 6663 lastMachineState, 6664 aReason)); 6665 rc = task->rc(); 6666 /* 6667 * If we fail here it means a PowerDown() call happened on another 6668 * thread while we were doing Pause() (which releases the Console lock). 6669 * We assign PowerDown() a higher precedence than SaveState(), 6670 * therefore just return the error to the caller. 6671 */ 6672 if (FAILED(rc)) 6673 { 6674 fTaskCreationFailed = true; 6675 break; 6676 } 6677 6678 /* create a thread to wait until the VM state is saved */ 6679 int vrc = RTThreadCreate(NULL, Console::i_saveStateThread, (void *)task.get(), 6680 0, RTTHREADTYPE_MAIN_WORKER, 0, "VMSave"); 6681 if (RT_FAILURE(vrc)) 6682 { 6683 rc = setError(E_FAIL, "Could not create VMSave thread (%Rrc)", vrc); 6684 break; 6685 } 6686 6687 /* task is now owned by saveStateThread(), so release it */ 6688 task.release(); 6689 6690 /* return the progress to the caller */ 6691 pProgress.queryInterfaceTo(aProgress); 6692 } while (0); 6693 6694 if (FAILED(rc) && !fTaskCreationFailed) 6695 { 6696 /* preserve existing error info */ 6697 ErrorInfoKeeper eik; 6698 6699 if (fBeganSavingState) 6700 { 6701 /* 6702 * cancel the requested save state procedure. 6703 * This will reset the machine state to the state it had right 6704 * before calling mControl->BeginSavingState(). 6705 */ 6706 mControl->EndSavingState(eik.getResultCode(), eik.getText().raw()); 6707 } 6708 6709 if (lastMachineState == MachineState_Running) 6710 { 6711 /* restore the paused state if appropriate */ 6712 i_setMachineStateLocally(MachineState_Paused); 6713 /* restore the running state if appropriate */ 6714 SafeVMPtr ptrVM(this); 6715 if (ptrVM.isOk()) 6716 { 6717 alock.release(); 6718 VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_RESTORED); 6719 alock.acquire(); 6720 } 6721 } 6722 else 6723 i_setMachineStateLocally(lastMachineState); 6724 } 6725 6726 LogFlowThisFunc(("rc=%Rhrc\n", rc)); 6727 LogFlowThisFuncLeave(); 6728 return rc; 6430 ptrVM.release(); 6431 alock.release(); 6432 autoCaller.release(); 6433 HRESULT rc = i_powerDown(); 6434 AssertComRC(rc); 6435 autoCaller.add(); 6436 alock.acquire(); 6437 } 6438 else 6439 { 6440 if (fPaused) 6441 aLeftPaused = true; 6442 } 6443 6444 LogFlowFuncLeave(); 6445 return S_OK; 6446 } 6447 6448 /** 6449 * Internal entry point for cancelling a VM save state. 6450 * 6451 * @note Locks this object for writing. 6452 */ 6453 HRESULT Console::i_cancelSaveState() 6454 { 6455 LogFlowThisFuncEnter(); 6456 6457 AutoCaller autoCaller(this); 6458 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 6459 6460 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 6461 6462 /* Get the VM handle. */ 6463 SafeVMPtr ptrVM(this); 6464 if (!ptrVM.isOk()) 6465 return ptrVM.rc(); 6466 6467 SSMR3Cancel(ptrVM.rawUVM()); 6468 6469 LogFlowFuncLeave(); 6470 return S_OK; 6729 6471 } 6730 6472 … … 6745 6487 6746 6488 AssertReturn( mMachineState == MachineState_Saving 6489 || mMachineState == MachineState_OnlineSnapshotting 6747 6490 || mMachineState == MachineState_LiveSnapshotting 6748 || mMachineState == MachineState_RestoringSnapshot6749 || mMachineState == MachineState_DeletingSnapshot6750 6491 || mMachineState == MachineState_DeletingSnapshotOnline 6751 6492 || mMachineState == MachineState_DeletingSnapshotPaused 6493 || aMachineState == MachineState_Saving 6494 || aMachineState == MachineState_OnlineSnapshotting 6495 || aMachineState == MachineState_LiveSnapshotting 6496 || aMachineState == MachineState_DeletingSnapshotOnline 6497 || aMachineState == MachineState_DeletingSnapshotPaused 6752 6498 , E_FAIL); 6753 6499 6754 6500 return i_setMachineStateLocally(aMachineState); 6501 } 6502 6503 /** 6504 * Gets called by Session::COMGETTER(NominalState)() 6505 * (IInternalSessionControl::getNominalState()). 6506 * 6507 * @note Locks this object for reading. 6508 */ 6509 HRESULT Console::i_getNominalState(MachineState_T &aNominalState) 6510 { 6511 LogFlowThisFuncEnter(); 6512 6513 AutoCaller autoCaller(this); 6514 AssertComRCReturnRC(autoCaller.rc()); 6515 6516 /* Get the VM handle. */ 6517 SafeVMPtr ptrVM(this); 6518 if (!ptrVM.isOk()) 6519 return ptrVM.rc(); 6520 6521 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 6522 6523 MachineState_T enmMachineState = MachineState_Null; 6524 VMSTATE enmVMState = VMR3GetStateU(ptrVM.rawUVM()); 6525 switch (enmVMState) 6526 { 6527 case VMSTATE_CREATING: 6528 case VMSTATE_CREATED: 6529 case VMSTATE_POWERING_ON: 6530 enmMachineState = MachineState_Starting; 6531 break; 6532 case VMSTATE_LOADING: 6533 enmMachineState = MachineState_Restoring; 6534 break; 6535 case VMSTATE_RESUMING: 6536 case VMSTATE_SUSPENDING: 6537 case VMSTATE_SUSPENDING_LS: 6538 case VMSTATE_SUSPENDING_EXT_LS: 6539 case VMSTATE_SUSPENDED: 6540 case VMSTATE_SUSPENDED_LS: 6541 case VMSTATE_SUSPENDED_EXT_LS: 6542 enmMachineState = MachineState_Paused; 6543 break; 6544 case VMSTATE_RUNNING: 6545 case VMSTATE_RUNNING_LS: 6546 case VMSTATE_RUNNING_FT: 6547 case VMSTATE_RESETTING: 6548 case VMSTATE_RESETTING_LS: 6549 case VMSTATE_DEBUGGING: 6550 case VMSTATE_DEBUGGING_LS: 6551 enmMachineState = MachineState_Running; 6552 break; 6553 case VMSTATE_SAVING: 6554 enmMachineState = MachineState_Saving; 6555 break; 6556 case VMSTATE_POWERING_OFF: 6557 case VMSTATE_POWERING_OFF_LS: 6558 case VMSTATE_DESTROYING: 6559 enmMachineState = MachineState_Stopping; 6560 break; 6561 case VMSTATE_OFF: 6562 case VMSTATE_OFF_LS: 6563 case VMSTATE_FATAL_ERROR: 6564 case VMSTATE_FATAL_ERROR_LS: 6565 case VMSTATE_LOAD_FAILURE: 6566 case VMSTATE_TERMINATED: 6567 enmMachineState = MachineState_PoweredOff; 6568 break; 6569 case VMSTATE_GURU_MEDITATION: 6570 case VMSTATE_GURU_MEDITATION_LS: 6571 enmMachineState = MachineState_Stuck; 6572 break; 6573 default: 6574 AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState))); 6575 enmMachineState = MachineState_PoweredOff; 6576 } 6577 aNominalState = enmMachineState; 6578 6579 LogFlowFuncLeave(); 6580 return S_OK; 6755 6581 } 6756 6582 … … 7160 6986 try 7161 6987 { 7162 7163 6988 if (Global::IsOnlineOrTransient(mMachineState)) 7164 6989 throw setError(VBOX_E_INVALID_VM_STATE, … … 7273 7098 } 7274 7099 7275 /* Setup task object and thread to carry out the operat on7276 * Asycnhronously */7100 /* Setup task object and thread to carry out the operation 7101 * asynchronously */ 7277 7102 std::auto_ptr<VMPowerUpTask> task(new VMPowerUpTask(this, pPowerupProgress)); 7278 7103 ComAssertComRCRetRC(task->rc()); … … 7892 7717 */ 7893 7718 HRESULT Console::i_setMachineState(MachineState_T aMachineState, 7894 bool aUpdateServer /* = true */)7719 bool aUpdateServer /* = true */) 7895 7720 { 7896 7721 AutoCaller autoCaller(this); … … 7905 7730 LogThisFunc(("machineState=%s -> %s aUpdateServer=%RTbool\n", 7906 7731 Global::stringifyMachineState(mMachineState), Global::stringifyMachineState(aMachineState), aUpdateServer)); 7732 LogRel(("Console: machine state changed to %s\n", Global::stringifyMachineState(aMachineState))); 7907 7733 mMachineState = aMachineState; 7908 7734 … … 8515 8341 8516 8342 case MachineState_LiveSnapshotting: 8517 that->i_setMachineState(MachineState_ Saving);8343 that->i_setMachineState(MachineState_OnlineSnapshotting); 8518 8344 break; 8519 8345 … … 8524 8350 case MachineState_TeleportingIn: 8525 8351 case MachineState_FaultTolerantSyncing: 8352 case MachineState_OnlineSnapshotting: 8526 8353 /* The worker thread handles the transition. */ 8527 8354 break; 8528 8355 8529 default:8530 AssertMsgFailed(("%s\n", Global::stringifyMachineState(that->mMachineState)));8531 8356 case MachineState_Running: 8532 8357 that->i_setMachineState(MachineState_Paused); … … 8536 8361 /* Nothing to do. */ 8537 8362 break; 8363 8364 default: 8365 AssertMsgFailed(("%s\n", Global::stringifyMachineState(that->mMachineState))); 8538 8366 } 8539 8367 break; … … 8553 8381 8554 8382 case MachineState_LiveSnapshotting: 8555 that->i_setMachineState(MachineState_ Saving);8383 that->i_setMachineState(MachineState_OnlineSnapshotting); 8556 8384 break; 8557 8385 … … 9613 9441 // Create the VMM device object, which starts the HGCM thread; do this only 9614 9442 // once for the console, for the pathological case that the same console 9615 // object is used to power up a VM twice. VirtualBox 4.0: we now do that 9616 // here instead of the Console constructor (see Console::init()) 9443 // object is used to power up a VM twice. 9617 9444 if (!pConsole->m_pVMMDev) 9618 9445 { … … 10102 9929 10103 9930 /** 10104 * Progress cancelation callback employed by Console::fntTakeSnapshotWorker.10105 */10106 static void takesnapshotProgressCancelCallback(void *pvUser)10107 {10108 PUVM pUVM = (PUVM)pvUser;10109 SSMR3Cancel(pUVM);10110 }10111 10112 /**10113 * Worker thread created by Console::TakeSnapshot.10114 * @param Thread The current thread (ignored).10115 * @param pvUser The task.10116 * @return VINF_SUCCESS (ignored).10117 */10118 /*static*/10119 DECLCALLBACK(int) Console::i_fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)10120 {10121 VMTakeSnapshotTask *pTask = (VMTakeSnapshotTask*)pvUser;10122 10123 // taking a snapshot consists of the following:10124 10125 // 1) creating a diff image for each virtual hard disk, into which write operations go after10126 // the snapshot has been created (done in VBoxSVC, in SessionMachine::BeginTakingSnapshot)10127 // 2) creating a Snapshot object with the state of the machine (hardware + storage,10128 // done in VBoxSVC, also in SessionMachine::BeginTakingSnapshot)10129 // 3) saving the state of the virtual machine (here, in the VM process, if the machine is online)10130 10131 Console *that = pTask->mConsole;10132 bool fBeganTakingSnapshot = false;10133 bool fSuspenededBySave = false;10134 10135 AutoCaller autoCaller(that);10136 if (FAILED(autoCaller.rc()))10137 {10138 that->mptrCancelableProgress.setNull();10139 return autoCaller.rc();10140 }10141 10142 AutoWriteLock alock(that COMMA_LOCKVAL_SRC_POS);10143 10144 HRESULT rc = S_OK;10145 10146 try10147 {10148 /* STEP 1 + 2:10149 * request creating the diff images on the server and create the snapshot object10150 * (this will set the machine state to Saving on the server to block10151 * others from accessing this machine)10152 */10153 rc = that->mControl->BeginTakingSnapshot(that,10154 pTask->bstrName.raw(),10155 pTask->bstrDescription.raw(),10156 pTask->mProgress,10157 pTask->fTakingSnapshotOnline,10158 pTask->bstrSavedStateFile.asOutParam());10159 if (FAILED(rc))10160 throw rc;10161 10162 fBeganTakingSnapshot = true;10163 10164 /* Check sanity: for offline snapshots there must not be a saved state10165 * file name. All other combinations are valid (even though online10166 * snapshots without saved state file seems inconsistent - there are10167 * some exotic use cases, which need to be explicitly enabled, see the10168 * code of SessionMachine::BeginTakingSnapshot. */10169 if ( !pTask->fTakingSnapshotOnline10170 && !pTask->bstrSavedStateFile.isEmpty())10171 throw i_setErrorStatic(E_FAIL, "Invalid state of saved state file");10172 10173 /* sync the state with the server */10174 if (pTask->lastMachineState == MachineState_Running)10175 that->i_setMachineStateLocally(MachineState_LiveSnapshotting);10176 else10177 that->i_setMachineStateLocally(MachineState_Saving);10178 10179 // STEP 3: save the VM state (if online)10180 if (pTask->fTakingSnapshotOnline)10181 {10182 int vrc;10183 SafeVMPtr ptrVM(that);10184 if (!ptrVM.isOk())10185 throw ptrVM.rc();10186 10187 pTask->mProgress->SetNextOperation(Bstr(tr("Saving the machine state")).raw(),10188 pTask->ulMemSize); // operation weight, same as computed10189 // when setting up progress object10190 if (!pTask->bstrSavedStateFile.isEmpty())10191 {10192 Utf8Str strSavedStateFile(pTask->bstrSavedStateFile);10193 10194 pTask->mProgress->i_setCancelCallback(takesnapshotProgressCancelCallback, ptrVM.rawUVM());10195 10196 alock.release();10197 LogFlowFunc(("VMR3Save...\n"));10198 vrc = VMR3Save(ptrVM.rawUVM(),10199 strSavedStateFile.c_str(),10200 true /*fContinueAfterwards*/,10201 Console::i_stateProgressCallback,10202 static_cast<IProgress *>(pTask->mProgress),10203 &fSuspenededBySave);10204 alock.acquire();10205 if (RT_FAILURE(vrc))10206 throw i_setErrorStatic(E_FAIL,10207 tr("Failed to save the machine state to '%s' (%Rrc)"),10208 strSavedStateFile.c_str(), vrc);10209 10210 pTask->mProgress->i_setCancelCallback(NULL, NULL);10211 }10212 else10213 LogRel(("Console: skipped saving state as part of online snapshot\n"));10214 10215 if (!pTask->mProgress->i_notifyPointOfNoReturn())10216 throw i_setErrorStatic(E_FAIL, tr("Canceled"));10217 that->mptrCancelableProgress.setNull();10218 10219 // STEP 4: reattach hard disks10220 LogFlowFunc(("Reattaching new differencing hard disks...\n"));10221 10222 pTask->mProgress->SetNextOperation(Bstr(tr("Reconfiguring medium attachments")).raw(),10223 1); // operation weight, same as computed when setting up progress object10224 10225 com::SafeIfaceArray<IMediumAttachment> atts;10226 rc = that->mMachine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(atts));10227 if (FAILED(rc))10228 throw rc;10229 10230 for (size_t i = 0;10231 i < atts.size();10232 ++i)10233 {10234 ComPtr<IStorageController> pStorageController;10235 Bstr controllerName;10236 ULONG lInstance;10237 StorageControllerType_T enmController;10238 StorageBus_T enmBus;10239 BOOL fUseHostIOCache;10240 10241 /*10242 * We can't pass a storage controller object directly10243 * (g++ complains about not being able to pass non POD types through '...')10244 * so we have to query needed values here and pass them.10245 */10246 rc = atts[i]->COMGETTER(Controller)(controllerName.asOutParam());10247 if (FAILED(rc))10248 throw rc;10249 10250 rc = that->mMachine->GetStorageControllerByName(controllerName.raw(),10251 pStorageController.asOutParam());10252 if (FAILED(rc))10253 throw rc;10254 10255 rc = pStorageController->COMGETTER(ControllerType)(&enmController);10256 if (FAILED(rc))10257 throw rc;10258 rc = pStorageController->COMGETTER(Instance)(&lInstance);10259 if (FAILED(rc))10260 throw rc;10261 rc = pStorageController->COMGETTER(Bus)(&enmBus);10262 if (FAILED(rc))10263 throw rc;10264 rc = pStorageController->COMGETTER(UseHostIOCache)(&fUseHostIOCache);10265 if (FAILED(rc))10266 throw rc;10267 10268 const char *pcszDevice = Console::i_convertControllerTypeToDev(enmController);10269 10270 BOOL fBuiltinIOCache;10271 rc = that->mMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache);10272 if (FAILED(rc))10273 throw rc;10274 10275 alock.release();10276 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,10277 (PFNRT)i_reconfigureMediumAttachment, 13,10278 that, ptrVM.rawUVM(), pcszDevice, lInstance, enmBus, fUseHostIOCache,10279 fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */,10280 0 /* uMergeTarget */, atts[i], that->mMachineState, &rc);10281 alock.acquire();10282 if (RT_FAILURE(vrc))10283 throw i_setErrorStatic(E_FAIL, Console::tr("%Rrc"), vrc);10284 if (FAILED(rc))10285 throw rc;10286 }10287 }10288 10289 /*10290 * finalize the requested snapshot object.10291 * This will reset the machine state to the state it had right10292 * before calling mControl->BeginTakingSnapshot().10293 */10294 rc = that->mControl->EndTakingSnapshot(TRUE /*aSuccess*/);10295 // do not throw rc here because we can't call EndTakingSnapshot() twice10296 LogFlowFunc(("EndTakingSnapshot -> %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(that->mMachineState)));10297 }10298 catch (HRESULT rcThrown)10299 {10300 /* preserve existing error info */10301 ErrorInfoKeeper eik;10302 10303 if (fBeganTakingSnapshot)10304 that->mControl->EndTakingSnapshot(FALSE /*aSuccess*/);10305 10306 rc = rcThrown;10307 LogFunc(("Caught %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(that->mMachineState)));10308 }10309 Assert(alock.isWriteLockOnCurrentThread());10310 10311 if (FAILED(rc)) /* Must come before calling setMachineState. */10312 pTask->mProgress->i_notifyComplete(rc);10313 10314 /*10315 * Fix up the machine state.10316 *10317 * For live snapshots we do all the work, for the two other variations we10318 * just update the local copy.10319 */10320 MachineState_T enmMachineState;10321 that->mMachine->COMGETTER(State)(&enmMachineState);10322 if ( that->mMachineState == MachineState_LiveSnapshotting10323 || that->mMachineState == MachineState_Saving)10324 {10325 10326 if (!pTask->fTakingSnapshotOnline)10327 that->i_setMachineStateLocally(pTask->lastMachineState);10328 else if (SUCCEEDED(rc))10329 {10330 Assert( pTask->lastMachineState == MachineState_Running10331 || pTask->lastMachineState == MachineState_Paused);10332 Assert(that->mMachineState == MachineState_Saving);10333 if (pTask->lastMachineState == MachineState_Running)10334 {10335 LogFlowFunc(("VMR3Resume...\n"));10336 SafeVMPtr ptrVM(that);10337 alock.release();10338 int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_SAVED);10339 alock.acquire();10340 if (RT_FAILURE(vrc))10341 {10342 rc = i_setErrorStatic(VBOX_E_VM_ERROR, tr("Could not resume the machine execution (%Rrc)"), vrc);10343 pTask->mProgress->i_notifyComplete(rc);10344 if (that->mMachineState == MachineState_Saving)10345 that->i_setMachineStateLocally(MachineState_Paused);10346 }10347 }10348 else10349 that->i_setMachineStateLocally(MachineState_Paused);10350 }10351 else10352 {10353 /** @todo this could probably be made more generic and reused elsewhere. */10354 /* paranoid cleanup on for a failed online snapshot. */10355 VMSTATE enmVMState = VMR3GetStateU(that->mpUVM);10356 switch (enmVMState)10357 {10358 case VMSTATE_RUNNING:10359 case VMSTATE_RUNNING_LS:10360 case VMSTATE_DEBUGGING:10361 case VMSTATE_DEBUGGING_LS:10362 case VMSTATE_POWERING_OFF:10363 case VMSTATE_POWERING_OFF_LS:10364 case VMSTATE_RESETTING:10365 case VMSTATE_RESETTING_LS:10366 Assert(!fSuspenededBySave);10367 that->i_setMachineState(MachineState_Running);10368 break;10369 10370 case VMSTATE_GURU_MEDITATION:10371 case VMSTATE_GURU_MEDITATION_LS:10372 that->i_setMachineState(MachineState_Stuck);10373 break;10374 10375 case VMSTATE_FATAL_ERROR:10376 case VMSTATE_FATAL_ERROR_LS:10377 if (pTask->lastMachineState == MachineState_Paused)10378 that->i_setMachineStateLocally(pTask->lastMachineState);10379 else10380 that->i_setMachineState(MachineState_Paused);10381 break;10382 10383 default:10384 AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState)));10385 case VMSTATE_SUSPENDED:10386 case VMSTATE_SUSPENDED_LS:10387 case VMSTATE_SUSPENDING:10388 case VMSTATE_SUSPENDING_LS:10389 case VMSTATE_SUSPENDING_EXT_LS:10390 if (fSuspenededBySave)10391 {10392 Assert(pTask->lastMachineState == MachineState_Running);10393 LogFlowFunc(("VMR3Resume (on failure)...\n"));10394 SafeVMPtr ptrVM(that);10395 alock.release();10396 int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_SAVED); AssertLogRelRC(vrc);10397 alock.acquire();10398 if (RT_FAILURE(vrc))10399 that->i_setMachineState(MachineState_Paused);10400 }10401 else if (pTask->lastMachineState == MachineState_Paused)10402 that->i_setMachineStateLocally(pTask->lastMachineState);10403 else10404 that->i_setMachineState(MachineState_Paused);10405 break;10406 }10407 10408 }10409 }10410 /*else: somebody else has change the state... Leave it. */10411 10412 /* check the remote state to see that we got it right. */10413 that->mMachine->COMGETTER(State)(&enmMachineState);10414 AssertLogRelMsg(that->mMachineState == enmMachineState,10415 ("mMachineState=%s enmMachineState=%s\n", Global::stringifyMachineState(that->mMachineState),10416 Global::stringifyMachineState(enmMachineState) ));10417 10418 10419 if (SUCCEEDED(rc)) /* The failure cases are handled above. */10420 pTask->mProgress->i_notifyComplete(rc);10421 10422 delete pTask;10423 10424 LogFlowFuncLeave();10425 return VINF_SUCCESS;10426 }10427 10428 /**10429 * Thread for executing the saved state operation.10430 *10431 * @param Thread The thread handle.10432 * @param pvUser Pointer to a VMSaveTask structure.10433 * @return VINF_SUCCESS (ignored).10434 *10435 * @note Locks the Console object for writing.10436 */10437 /*static*/10438 DECLCALLBACK(int) Console::i_saveStateThread(RTTHREAD Thread, void *pvUser)10439 {10440 LogFlowFuncEnter();10441 10442 std::auto_ptr<VMSaveTask> task(static_cast<VMSaveTask*>(pvUser));10443 AssertReturn(task.get(), VERR_INVALID_PARAMETER);10444 10445 Assert(task->mSavedStateFile.length());10446 Assert(task->mProgress.isNull());10447 Assert(!task->mServerProgress.isNull());10448 10449 const ComObjPtr<Console> &that = task->mConsole;10450 Utf8Str errMsg;10451 HRESULT rc = S_OK;10452 10453 LogFlowFunc(("Saving the state to '%s'...\n", task->mSavedStateFile.c_str()));10454 10455 bool fSuspenededBySave;10456 int vrc = VMR3Save(task->mpUVM,10457 task->mSavedStateFile.c_str(),10458 false, /*fContinueAfterwards*/10459 Console::i_stateProgressCallback,10460 static_cast<IProgress *>(task->mServerProgress),10461 &fSuspenededBySave);10462 if (RT_FAILURE(vrc))10463 {10464 errMsg = Utf8StrFmt(Console::tr("Failed to save the machine state to '%s' (%Rrc)"),10465 task->mSavedStateFile.c_str(), vrc);10466 rc = E_FAIL;10467 }10468 Assert(!fSuspenededBySave);10469 10470 /* lock the console once we're going to access it */10471 AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS);10472 10473 /* synchronize the state with the server */10474 if (SUCCEEDED(rc))10475 {10476 /*10477 * The machine has been successfully saved, so power it down10478 * (vmstateChangeCallback() will set state to Saved on success).10479 * Note: we release the task's VM caller, otherwise it will10480 * deadlock.10481 */10482 task->releaseVMCaller();10483 thatLock.release();10484 rc = that->i_powerDown();10485 thatLock.acquire();10486 }10487 10488 /*10489 * If we failed, reset the local machine state.10490 */10491 if (FAILED(rc))10492 that->i_setMachineStateLocally(task->mMachineStateBefore);10493 10494 /*10495 * Finalize the requested save state procedure. In case of failure it will10496 * reset the machine state to the state it had right before calling10497 * mControl->BeginSavingState(). This must be the last thing because it10498 * will set the progress to completed, and that means that the frontend10499 * can immediately uninit the associated console object.10500 */10501 that->mControl->EndSavingState(rc, Bstr(errMsg).raw());10502 10503 LogFlowFuncLeave();10504 return VINF_SUCCESS;10505 }10506 10507 /**10508 9931 * Thread for powering down the Console. 10509 9932 * … … 10560 9983 /* 10561 9984 * For now, just call SaveState. We should probably try notify the GUI so 10562 * it can pop up a progress object and stuff. 9985 * it can pop up a progress object and stuff. The progress object created 9986 * by the call isn't returned to anyone and thus gets updated without 9987 * anyone noticing it. 10563 9988 */ 10564 HRESULT hrc = pConsole->SaveState(NULL); 9989 ComPtr<IProgress> pProgress; 9990 HRESULT hrc = pConsole->mMachine->SaveState(pProgress.asOutParam()); 10565 9991 return SUCCEEDED(hrc) ? VINF_SUCCESS : Global::vboxStatusCodeFromCOM(hrc); 10566 9992 } -
trunk/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp
r51612 r55214 5 5 6 6 /* 7 * Copyright (C) 2010-201 4Oracle Corporation7 * Copyright (C) 2010-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 997 997 { 998 998 ptrProgress.queryInterfaceTo(aProgress.asOutParam()); 999 mptrCancelableProgress = ptrProgress;999 mptrCancelableProgress = aProgress; 1000 1000 } 1001 1001 else -
trunk/src/VBox/Main/src-client/SessionImpl.cpp
r53062 r55214 123 123 mState == SessionState_Spawning); 124 124 125 HRESULT rc = unlockMachine(true /* aFinalRelease */, false /* aFromServer */);125 HRESULT rc = i_unlockMachine(true /* aFinalRelease */, false /* aFromServer */); 126 126 AssertComRC(rc); 127 127 } … … 167 167 if (FAILED(rc)) 168 168 { 169 /** @todo VBox 3.3: replace E_FAIL with rc here. */170 169 #ifndef VBOX_COM_INPROC_API_CLIENT 171 170 if (mConsole) 172 setError( E_FAIL, tr("Failed to query the session machine (%Rhrc)"), rc);171 setError(rc, tr("Failed to query the session machine")); 173 172 else 174 173 #endif 175 174 if (FAILED_DEAD_INTERFACE(rc)) 176 setError( E_FAIL, tr("Peer process crashed"));175 setError(rc, tr("Peer process crashed")); 177 176 else 178 setError( E_FAIL, tr("Failed to query the remote session machine (%Rhrc)"), rc);177 setError(rc, tr("Failed to query the remote session machine")); 179 178 } 180 179 … … 198 197 if (FAILED(rc)) 199 198 { 200 /** @todo VBox 3.3: replace E_FAIL with rc here. */201 199 #ifndef VBOX_COM_INPROC_API_CLIENT 202 200 if (mConsole) 203 setError( E_FAIL, tr("Failed to query the console (%Rhrc)"), rc);201 setError(rc, tr("Failed to query the console")); 204 202 else 205 203 #endif 206 204 if (FAILED_DEAD_INTERFACE(rc)) 207 setError( E_FAIL, tr("Peer process crashed"));205 setError(rc, tr("Peer process crashed")); 208 206 else 209 setError( E_FAIL, tr("Failed to query the remote console (%Rhrc)"), rc);207 setError(rc, tr("Failed to query the remote console")); 210 208 } 211 209 … … 224 222 CHECK_OPEN(); 225 223 226 return unlockMachine(false /* aFinalRelease */, false /* aFromServer */);224 return i_unlockMachine(false /* aFinalRelease */, false /* aFromServer */); 227 225 } 228 226 … … 265 263 return VBOX_E_INVALID_OBJECT_STATE; 266 264 #endif /* VBOX_COM_INPROC_API_CLIENT */ 265 } 266 267 HRESULT Session::getNominalState(MachineState_T *aNominalState) 268 { 269 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 270 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 271 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 272 #ifndef VBOX_COM_INPROC_API_CLIENT 273 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 274 275 return mConsole->i_getNominalState(*aNominalState); 276 #else 277 AssertFailed(); 278 return E_NOTIMPL; 279 #endif 267 280 } 268 281 … … 300 313 AssertReturn(!!mControl, E_FAIL); 301 314 302 #ifndef VBOX_COM_INPROC_API_CLIENT303 HRESULT rc = mConsole.createObject();304 AssertComRCReturn(rc, rc);305 306 rc = mConsole->init(aMachine, mControl, aLockType);307 AssertComRCReturn(rc, rc);308 #else309 315 HRESULT rc = S_OK; 316 #ifndef VBOX_COM_INPROC_API_CLIENT 317 if (aLockType == LockType_VM) 318 { 319 /* This is what is special about VM processes: they have a Console 320 * object which is the root of all VM related activity. */ 321 rc = mConsole.createObject(); 322 AssertComRCReturn(rc, rc); 323 324 rc = mConsole->init(aMachine, mControl, aLockType); 325 AssertComRCReturn(rc, rc); 326 } 327 else 328 mRemoteMachine = aMachine; 329 #else 310 330 mRemoteMachine = aMachine; 311 331 #endif … … 369 389 370 390 { 371 AssertReturn(aMachine && aConsole, E_INVALIDARG);391 AssertReturn(aMachine, E_INVALIDARG); 372 392 373 393 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); … … 496 516 497 517 /* close ourselves */ 498 rc = unlockMachine(false /* aFinalRelease */, true /* aFromServer */);518 rc = i_unlockMachine(false /* aFinalRelease */, true /* aFromServer */); 499 519 } 500 520 else if (getObjectState().getState() == ObjectState::InUninit) … … 721 741 #ifndef VBOX_COM_INPROC_API_CLIENT 722 742 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 743 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 723 744 724 745 return mConsole->i_onDnDModeChange(aDndMode); … … 911 932 } 912 933 913 HRESULT Session:: enableVMMStatistics(BOOL aEnable)914 { 915 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);916 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);917 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);918 #ifndef VBOX_COM_INPROC_API_CLIENT 919 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 920 921 mConsole->i_enableVMMStatistics(aEnable);922 923 return S_OK;934 HRESULT Session::reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments) 935 { 936 if (mState != SessionState_Locked) 937 return setError(VBOX_E_INVALID_VM_STATE, 938 tr("Machine is not locked by session (session state: %s)."), 939 Global::stringifySessionState(mState)); 940 #ifndef VBOX_COM_INPROC_API_CLIENT 941 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 942 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 943 944 return mConsole->i_reconfigureMediumAttachments(aAttachments); 924 945 #else 925 946 AssertFailed(); … … 928 949 } 929 950 930 HRESULT Session::pauseWithReason(Reason_T aReason) 931 { 932 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 933 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 934 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 935 #ifndef VBOX_COM_INPROC_API_CLIENT 936 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 937 938 return mConsole->i_pause(aReason); 951 HRESULT Session::enableVMMStatistics(BOOL aEnable) 952 { 953 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 954 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 955 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 956 #ifndef VBOX_COM_INPROC_API_CLIENT 957 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 958 959 mConsole->i_enableVMMStatistics(aEnable); 960 961 return S_OK; 939 962 #else 940 963 AssertFailed(); … … 943 966 } 944 967 945 HRESULT Session:: resumeWithReason(Reason_T aReason)946 { 947 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 948 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 949 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 950 #ifndef VBOX_COM_INPROC_API_CLIENT 951 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 952 953 return mConsole->i_ resume(aReason);968 HRESULT Session::pauseWithReason(Reason_T aReason) 969 { 970 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 971 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 972 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 973 #ifndef VBOX_COM_INPROC_API_CLIENT 974 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 975 976 return mConsole->i_pause(aReason); 954 977 #else 955 978 AssertFailed(); … … 958 981 } 959 982 960 HRESULT Session::saveStateWithReason(Reason_T aReason, ComPtr<IProgress> &aProgress) 961 { 962 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 963 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 964 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 965 #ifndef VBOX_COM_INPROC_API_CLIENT 966 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 967 968 return mConsole->i_saveState(aReason, aProgress.asOutParam()); 983 HRESULT Session::resumeWithReason(Reason_T aReason) 984 { 985 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 986 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 987 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 988 #ifndef VBOX_COM_INPROC_API_CLIENT 989 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 990 991 AutoWriteLock dummyLock(mConsole COMMA_LOCKVAL_SRC_POS); 992 return mConsole->i_resume(aReason, dummyLock); 993 #else 994 AssertFailed(); 995 return E_NOTIMPL; 996 #endif 997 } 998 999 HRESULT Session::saveStateWithReason(Reason_T aReason, const ComPtr<IProgress> &aProgress, const Utf8Str &aStateFilePath, BOOL aPauseVM, BOOL *aLeftPaused) 1000 { 1001 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1002 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 1003 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 1004 #ifndef VBOX_COM_INPROC_API_CLIENT 1005 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 1006 1007 bool fLeftPaused = false; 1008 HRESULT rc = mConsole->i_saveState(aReason, aProgress, aStateFilePath, !!aPauseVM, fLeftPaused); 1009 if (aLeftPaused) 1010 *aLeftPaused = fLeftPaused; 1011 return rc; 1012 #else 1013 AssertFailed(); 1014 return E_NOTIMPL; 1015 #endif 1016 } 1017 1018 HRESULT Session::cancelSaveStateWithReason() 1019 { 1020 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1021 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 1022 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 1023 #ifndef VBOX_COM_INPROC_API_CLIENT 1024 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 1025 1026 return mConsole->i_cancelSaveState(); 969 1027 #else 970 1028 AssertFailed(); … … 985 1043 * @note Locks this object for writing. 986 1044 */ 987 HRESULT Session:: unlockMachine(bool aFinalRelease, bool aFromServer)1045 HRESULT Session::i_unlockMachine(bool aFinalRelease, bool aFromServer) 988 1046 { 989 1047 LogFlowThisFuncEnter(); -
trunk/src/VBox/Main/src-server/HostPower.cpp
r51498 r55214 5 5 6 6 /* 7 * Copyright (C) 2006-201 4Oracle Corporation7 * Copyright (C) 2006-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 139 139 140 140 /* save running VMs */ 141 SessionMachinesList::const_iterator it2 = machines.begin(); 142 for (VirtualBox::InternalControlList::const_iterator it = controls.begin(); 143 it != controls.end() && it2 != machines.end(); 144 ++it, ++it2) 141 for (SessionMachinesList::const_iterator it = machines.begin(); 142 it != machines.end(); 143 ++it) 145 144 { 146 ComPtr<SessionMachine> pMachine = *it 2;145 ComPtr<SessionMachine> pMachine = *it; 147 146 rc = pMachine->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(), 148 147 value.asOutParam()); … … 160 159 if (fGlobal + fPerVM >= 0) 161 160 { 162 ComPtr<IInternalSessionControl> pControl = *it;163 161 ComPtr<IProgress> progress; 164 162 165 /* note that SaveStateWithReason() will simply return a failure166 * if the VM is in an inappropriate state */167 rc = p Control->SaveStateWithReason(Reason_HostBatteryLow, progress.asOutParam());163 /* SessionMachine::i_saveStateWithReason() will return 164 * a failure if the VM is in an inappropriate state */ 165 rc = pMachine->i_saveStateWithReason(Reason_HostBatteryLow, progress); 168 166 if (FAILED(rc)) 169 167 { -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r55168 r55214 131 131 132 132 mSession.mPID = NIL_RTPROCESS; 133 mSession.mLockType = LockType_Null; 133 134 mSession.mState = SessionState_Unlocked; 134 135 } … … 2694 2695 2695 2696 *aState = mData->mMachineState; 2697 Assert(mData->mMachineState != MachineState_Null); 2696 2698 2697 2699 return S_OK; … … 3248 3250 3249 3251 // copy pointers to W (the write-locking session) before leaving lock (these must not be NULL) 3252 ComAssertRet(mData->mSession.mLockType == LockType_Write || mData->mSession.mLockType == LockType_VM, E_FAIL); 3250 3253 ComPtr<IInternalSessionControl> pSessionW = mData->mSession.mDirectControl; 3251 3254 ComAssertRet(!pSessionW.isNull(), E_FAIL); … … 3263 3266 // get the console of the session holding the write lock (this is a remote call) 3264 3267 ComPtr<IConsole> pConsoleW; 3265 LogFlowThisFunc(("Calling GetRemoteConsole()...\n")); 3266 rc = pSessionW->GetRemoteConsole(pConsoleW.asOutParam()); 3267 LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc)); 3268 if (FAILED(rc)) 3269 // the failure may occur w/o any error info (from RPC), so provide one 3270 return setError(VBOX_E_VM_ERROR, 3271 tr("Failed to get a console object from the direct session (%Rhrc)"), rc); 3272 3273 ComAssertRet(!pConsoleW.isNull(), E_FAIL); 3268 if (mData->mSession.mLockType == LockType_VM) 3269 { 3270 LogFlowThisFunc(("Calling GetRemoteConsole()...\n")); 3271 rc = pSessionW->COMGETTER(RemoteConsole)(pConsoleW.asOutParam()); 3272 LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc)); 3273 if (FAILED(rc)) 3274 // the failure may occur w/o any error info (from RPC), so provide one 3275 return setError(VBOX_E_VM_ERROR, 3276 tr("Failed to get a console object from the direct session (%Rhrc)"), rc); 3277 ComAssertRet(!pConsoleW.isNull(), E_FAIL); 3278 } 3274 3279 3275 3280 // share the session machine and W's console with the caller's session … … 3315 3320 RTPROCESS pid = NIL_RTPROCESS; 3316 3321 AssertCompile(sizeof(ULONG) == sizeof(RTPROCESS)); 3317 pSessionControl-> GetPID((ULONG*)&pid);3322 pSessionControl->COMGETTER(PID)((ULONG*)&pid); 3318 3323 Assert(pid != NIL_RTPROCESS); 3319 3324 … … 3432 3437 /* get the console from the direct session */ 3433 3438 ComPtr<IConsole> console; 3434 rc = pSessionControl-> GetRemoteConsole(console.asOutParam());3439 rc = pSessionControl->COMGETTER(RemoteConsole)(console.asOutParam()); 3435 3440 ComAssertComRC(rc); 3436 3441 … … 3505 3510 if (SUCCEEDED(rc)) 3506 3511 { 3512 mData->mSession.mLockType = aLockType; 3507 3513 /* memorize the direct session control and cache IUnknown for it */ 3508 3514 mData->mSession.mDirectControl = pSessionControl; … … 3525 3531 if (FAILED(rc)) 3526 3532 sessionMachine->uninit(); 3527 3528 3533 } 3529 3534 … … 5172 5177 } 5173 5178 5174 struct Machine::DeleteTask 5175 { 5176 ComObjPtr<Machine> pMachine; 5177 RTCList<ComPtr<IMedium> > llMediums; 5178 StringsList llFilesToDelete; 5179 ComObjPtr<Progress> pProgress; 5179 /** 5180 * Task record for deleting a machine config. 5181 */ 5182 struct Machine::DeleteConfigTask 5183 : public Machine::Task 5184 { 5185 DeleteConfigTask(Machine *m, 5186 Progress *p, 5187 const Utf8Str &t, 5188 const RTCList<ComPtr<IMedium> > &llMediums, 5189 const StringsList &llFilesToDelete) 5190 : Task(m, p, t), 5191 m_llMediums(llMediums), 5192 m_llFilesToDelete(llFilesToDelete) 5193 {} 5194 5195 void handler() 5196 { 5197 m_pMachine->i_deleteConfigHandler(*this); 5198 } 5199 5200 RTCList<ComPtr<IMedium> > m_llMediums; 5201 StringsList m_llFilesToDelete; 5180 5202 }; 5181 5203 5182 HRESULT Machine::deleteConfig(const std::vector<ComPtr<IMedium> > &aMedia, ComPtr<IProgress> &aProgress)5183 {5184 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);5185 5186 HRESULT rc = i_checkStateDependency(MutableStateDep);5187 if (FAILED(rc)) return rc;5188 5189 if (mData->mRegistered)5190 return setError(VBOX_E_INVALID_VM_STATE,5191 tr("Cannot delete settings of a registered machine"));5192 5193 DeleteTask *pTask = new DeleteTask;5194 pTask->pMachine = this;5195 5196 // collect files to delete5197 pTask->llFilesToDelete = mData->llFilesToDelete; // saved states pushed here by Unregister()5198 5199 for (size_t i = 0; i < aMedia.size(); ++i)5200 {5201 IMedium *pIMedium(aMedia[i]);5202 ComObjPtr<Medium> pMedium = static_cast<Medium*>(pIMedium);5203 if (pMedium.isNull())5204 return setError(E_INVALIDARG, "The given medium pointer with index %d is invalid", i);5205 SafeArray<BSTR> ids;5206 rc = pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(ids));5207 if (FAILED(rc)) return rc;5208 /* At this point the medium should not have any back references5209 * anymore. If it has it is attached to another VM and *must* not5210 * deleted. */5211 if (ids.size() < 1)5212 pTask->llMediums.append(pMedium);5213 }5214 if (mData->pMachineConfigFile->fileExists())5215 pTask->llFilesToDelete.push_back(mData->m_strConfigFileFull);5216 5217 pTask->pProgress.createObject();5218 pTask->pProgress->init(i_getVirtualBox(),5219 static_cast<IMachine*>(this) /* aInitiator */,5220 Bstr(tr("Deleting files")).raw(),5221 true /* fCancellable */,5222 (ULONG)(pTask->llFilesToDelete.size() + pTask->llMediums.size() + 1), // cOperations5223 BstrFmt(tr("Deleting '%s'"), pTask->llFilesToDelete.front().c_str()).raw());5224 5225 int vrc = RTThreadCreate(NULL,5226 Machine::deleteThread,5227 (void*)pTask,5228 0,5229 RTTHREADTYPE_MAIN_WORKER,5230 0,5231 "MachineDelete");5232 5233 pTask->pProgress.queryInterfaceTo(aProgress.asOutParam());5234 5235 if (RT_FAILURE(vrc))5236 {5237 delete pTask;5238 return setError(E_FAIL, "Could not create MachineDelete thread (%Rrc)", vrc);5239 }5240 5241 LogFlowFuncLeave();5242 5243 return S_OK;5244 }5245 5246 5204 /** 5247 * Static task wrapper passed to RTThreadCreate() in Machine::Delete() which then 5248 * calls Machine::deleteTaskWorker() on the actual machine object. 5249 * @param Thread 5250 * @param pvUser 5251 * @return 5252 */ 5253 /*static*/ 5254 DECLCALLBACK(int) Machine::deleteThread(RTTHREAD Thread, void *pvUser) 5255 { 5256 LogFlowFuncEnter(); 5257 5258 DeleteTask *pTask = (DeleteTask*)pvUser; 5259 Assert(pTask); 5260 Assert(pTask->pMachine); 5261 Assert(pTask->pProgress); 5262 5263 HRESULT rc = pTask->pMachine->i_deleteTaskWorker(*pTask); 5264 pTask->pProgress->i_notifyComplete(rc); 5265 5266 delete pTask; 5267 5268 LogFlowFuncLeave(); 5269 5270 NOREF(Thread); 5271 5272 return VINF_SUCCESS; 5273 } 5274 5275 /** 5276 * Task thread implementation for Machine::Delete(), called from Machine::deleteThread(). 5205 * Task thread implementation for SessionMachine::DeleteConfig(), called from 5206 * SessionMachine::taskHandler(). 5207 * 5208 * @note Locks this object for writing. 5209 * 5277 5210 * @param task 5278 5211 * @return 5279 5212 */ 5280 HRESULT Machine::i_deleteTaskWorker(DeleteTask &task) 5281 { 5213 void Machine::i_deleteConfigHandler(DeleteConfigTask &task) 5214 { 5215 LogFlowThisFuncEnter(); 5216 5282 5217 AutoCaller autoCaller(this); 5283 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 5218 LogFlowThisFunc(("state=%d\n", getObjectState().getState())); 5219 if (FAILED(autoCaller.rc())) 5220 { 5221 /* we might have been uninitialized because the session was accidentally 5222 * closed by the client, so don't assert */ 5223 HRESULT rc = setError(E_FAIL, 5224 tr("The session has been accidentally closed")); 5225 task.m_pProgress->i_notifyComplete(rc); 5226 LogFlowThisFuncLeave(); 5227 return; 5228 } 5284 5229 5285 5230 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); … … 5303 5248 i_setMachineState(MachineState_SettingUp); 5304 5249 alock.release(); 5305 for (size_t i = 0; i < task. llMediums.size(); ++i)5306 { 5307 ComObjPtr<Medium> pMedium = (Medium*)(IMedium*) task.llMediums.at(i);5250 for (size_t i = 0; i < task.m_llMediums.size(); ++i) 5251 { 5252 ComObjPtr<Medium> pMedium = (Medium*)(IMedium*)(task.m_llMediums.at(i)); 5308 5253 { 5309 5254 AutoCaller mac(pMedium); 5310 5255 if (FAILED(mac.rc())) throw mac.rc(); 5311 5256 Utf8Str strLocation = pMedium->i_getLocationFull(); 5312 rc = task. pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), strLocation.c_str()).raw(), 1);5257 rc = task.m_pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), strLocation.c_str()).raw(), 1); 5313 5258 if (FAILED(rc)) throw rc; 5314 5259 LogFunc(("Deleting file %s\n", strLocation.c_str())); … … 5319 5264 rc = pMedium->DeleteStorage(pProgress2.asOutParam()); 5320 5265 if (FAILED(rc)) throw rc; 5321 rc = task. pProgress->WaitForAsyncProgressCompletion(pProgress2);5266 rc = task.m_pProgress->WaitForAsyncProgressCompletion(pProgress2); 5322 5267 if (FAILED(rc)) throw rc; 5323 5268 /* Check the result of the asynchronous process. */ … … 5347 5292 // medium storage files from the IMedium list passed in, and the 5348 5293 // machine XML file) 5349 StringsList::const_iterator it = task. llFilesToDelete.begin();5350 while (it != task. llFilesToDelete.end())5294 StringsList::const_iterator it = task.m_llFilesToDelete.begin(); 5295 while (it != task.m_llFilesToDelete.end()) 5351 5296 { 5352 5297 const Utf8Str &strFile = *it; … … 5358 5303 5359 5304 ++it; 5360 if (it == task. llFilesToDelete.end())5305 if (it == task.m_llFilesToDelete.end()) 5361 5306 { 5362 rc = task. pProgress->SetNextOperation(Bstr(tr("Cleaning up machine directory")).raw(), 1);5307 rc = task.m_pProgress->SetNextOperation(Bstr(tr("Cleaning up machine directory")).raw(), 1); 5363 5308 if (FAILED(rc)) throw rc; 5364 5309 break; 5365 5310 } 5366 5311 5367 rc = task. pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), it->c_str()).raw(), 1);5312 rc = task.m_pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), it->c_str()).raw(), 1); 5368 5313 if (FAILED(rc)) throw rc; 5369 5314 } … … 5438 5383 catch (HRESULT aRC) { rc = aRC; } 5439 5384 5440 return rc; 5385 task.m_pProgress->i_notifyComplete(rc); 5386 5387 LogFlowThisFuncLeave(); 5388 } 5389 5390 HRESULT Machine::deleteConfig(const std::vector<ComPtr<IMedium> > &aMedia, ComPtr<IProgress> &aProgress) 5391 { 5392 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 5393 5394 HRESULT rc = i_checkStateDependency(MutableStateDep); 5395 if (FAILED(rc)) return rc; 5396 5397 if (mData->mRegistered) 5398 return setError(VBOX_E_INVALID_VM_STATE, 5399 tr("Cannot delete settings of a registered machine")); 5400 5401 // collect files to delete 5402 StringsList llFilesToDelete(mData->llFilesToDelete); // saved states pushed here by Unregister() 5403 if (mData->pMachineConfigFile->fileExists()) 5404 llFilesToDelete.push_back(mData->m_strConfigFileFull); 5405 5406 RTCList<ComPtr<IMedium> > llMediums; 5407 for (size_t i = 0; i < aMedia.size(); ++i) 5408 { 5409 IMedium *pIMedium(aMedia[i]); 5410 ComObjPtr<Medium> pMedium = static_cast<Medium*>(pIMedium); 5411 if (pMedium.isNull()) 5412 return setError(E_INVALIDARG, "The given medium pointer with index %d is invalid", i); 5413 SafeArray<BSTR> ids; 5414 rc = pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(ids)); 5415 if (FAILED(rc)) return rc; 5416 /* At this point the medium should not have any back references 5417 * anymore. If it has it is attached to another VM and *must* not 5418 * deleted. */ 5419 if (ids.size() < 1) 5420 llMediums.append(pMedium); 5421 } 5422 5423 ComObjPtr<Progress> pProgress; 5424 pProgress.createObject(); 5425 rc = pProgress->init(i_getVirtualBox(), 5426 static_cast<IMachine*>(this) /* aInitiator */, 5427 Bstr(tr("Deleting files")).raw(), 5428 true /* fCancellable */, 5429 (ULONG)(llFilesToDelete.size() + llMediums.size() + 1), // cOperations 5430 BstrFmt(tr("Deleting '%s'"), llFilesToDelete.front().c_str()).raw()); 5431 if (FAILED(rc)) 5432 return rc; 5433 5434 /* create and start the task on a separate thread (note that it will not 5435 * start working until we release alock) */ 5436 DeleteConfigTask *pTask = new DeleteConfigTask(this, pProgress, "DeleteVM", llMediums, llFilesToDelete); 5437 rc = pTask->createThread(); 5438 if (FAILED(rc)) 5439 return rc; 5440 5441 pProgress.queryInterfaceTo(aProgress.asOutParam()); 5442 5443 LogFlowFuncLeave(); 5444 5445 return S_OK; 5441 5446 } 5442 5447 … … 5534 5539 Global::stringifySessionState(mData->mSession.mState)); 5535 5540 5536 directControl = mData->mSession.mDirectControl; 5541 if (mData->mSession.mLockType == LockType_VM) 5542 directControl = mData->mSession.mDirectControl; 5537 5543 } 5538 5544 … … 5556 5562 Global::stringifySessionState(mData->mSession.mState)); 5557 5563 5558 directControl = mData->mSession.mDirectControl; 5564 if (mData->mSession.mLockType == LockType_VM) 5565 directControl = mData->mSession.mDirectControl; 5559 5566 } 5560 5567 … … 5609 5616 5610 5617 ComPtr<IInternalSessionControl> directControl; 5611 directControl = mData->mSession.mDirectControl; 5612 5613 /* fail if we were called after #OnSessionEnd() is called. This is a 5614 * silly race condition. */ 5615 5616 /** @todo This code is bothering API clients (like python script clients) with 5617 * the AccessGuestProperty call, creating unncessary IPC. Need to 5618 * have a way of figuring out which kind of direct session it is... */ 5618 { 5619 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 5620 if (mData->mSession.mLockType == LockType_VM) 5621 directControl = mData->mSession.mDirectControl; 5622 } 5623 5624 /* ignore calls made after #OnSessionEnd() is called */ 5619 5625 if (!directControl) 5620 5626 rc = E_ACCESSDENIED; … … 5769 5775 try 5770 5776 { 5771 ComPtr<IInternalSessionControl> directControl = mData->mSession.mDirectControl; 5777 ComPtr<IInternalSessionControl> directControl; 5778 { 5779 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 5780 if (mData->mSession.mLockType == LockType_VM) 5781 directControl = mData->mSession.mDirectControl; 5782 } 5772 5783 5773 5784 BSTR dummy = NULL; /* will not be changed (setter) */ … … 5896 5907 HRESULT rc; 5897 5908 ComPtr<IInternalSessionControl> directControl; 5898 directControl = mData->mSession.mDirectControl; 5899 5909 { 5910 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 5911 if (mData->mSession.mLockType == LockType_VM) 5912 directControl = mData->mSession.mDirectControl; 5913 } 5900 5914 5901 5915 com::SafeArray<BSTR> bNames; … … 7086 7100 return rc; 7087 7101 7102 } 7103 7104 HRESULT Machine::saveState(ComPtr<IProgress> &aProgress) 7105 { 7106 NOREF(aProgress); 7107 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 7108 7109 // This check should always fail. 7110 HRESULT rc = i_checkStateDependency(MutableStateDep); 7111 if (FAILED(rc)) return rc; 7112 7113 AssertFailedReturn(E_NOTIMPL); 7114 } 7115 7116 HRESULT Machine::adoptSavedState(const com::Utf8Str &aSavedStateFile) 7117 { 7118 NOREF(aSavedStateFile); 7119 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 7120 7121 // This check should always fail. 7122 HRESULT rc = i_checkStateDependency(MutableStateDep); 7123 if (FAILED(rc)) return rc; 7124 7125 AssertFailedReturn(E_NOTIMPL); 7126 } 7127 7128 HRESULT Machine::discardSavedState(BOOL aFRemoveFile) 7129 { 7130 NOREF(aFRemoveFile); 7131 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 7132 7133 // This check should always fail. 7134 HRESULT rc = i_checkStateDependency(MutableStateDep); 7135 if (FAILED(rc)) return rc; 7136 7137 AssertFailedReturn(E_NOTIMPL); 7088 7138 } 7089 7139 … … 7718 7768 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 7719 7769 7720 if ( mData->mSession.mState == SessionState_Locked 7770 if ( ( mData->mSession.mState == SessionState_Locked 7771 && mData->mSession.mLockType == LockType_VM) 7721 7772 || (aAllowClosing && mData->mSession.mState == SessionState_Unlocking) 7722 7773 ) … … 8419 8470 LogFlowThisFuncEnter(); 8420 8471 LogFlowThisFunc(("aMachineState=%s\n", Global::stringifyMachineState(aMachineState) )); 8472 Assert(aMachineState != MachineState_Null); 8421 8473 8422 8474 AutoCaller autoCaller(this); … … 10581 10633 10582 10634 /* must be in a protective state because we release the lock below */ 10583 AssertReturn( mData->mMachineState == MachineState_Saving 10635 AssertReturn( mData->mMachineState == MachineState_Snapshotting 10636 || mData->mMachineState == MachineState_OnlineSnapshotting 10584 10637 || mData->mMachineState == MachineState_LiveSnapshotting 10585 10638 || mData->mMachineState == MachineState_RestoringSnapshot … … 10670 10723 /* copy the attachment as is */ 10671 10724 10672 /** @todo the progress object created in Console::TakeSnaphot10725 /** @todo the progress object created in SessionMachine::TakeSnaphot 10673 10726 * only expects operations for hard disks. Later other 10674 10727 * device types need to show up in the progress as well. */ … … 10832 10885 /* will release the lock before the potentially lengthy operation, 10833 10886 * so protect with the special state (unless already protected) */ 10834 if ( oldState != MachineState_Saving 10887 if ( oldState != MachineState_Snapshotting 10888 && oldState != MachineState_OnlineSnapshotting 10835 10889 && oldState != MachineState_LiveSnapshotting 10836 10890 && oldState != MachineState_RestoringSnapshot … … 10969 11023 mrc = rc; 10970 11024 } 11025 // Clear the list of deleted implicit attachments now, while not 11026 // holding the lock, as it will ultimately trigger Medium::uninit() 11027 // calls which assume that the media tree lock isn't held. 11028 implicitAtts.clear(); 10971 11029 10972 11030 alock.acquire(); … … 12490 12548 } 12491 12549 12492 Assert( mConsoleTaskData.strStateFilePath.isEmpty()12493 || !mConsoleTaskData.mSnapshot);12494 if (!mConsoleTaskData.strStateFilePath.isEmpty())12495 {12496 LogWarningThisFunc(("canceling failed save state request!\n"));12497 endSavingState(E_FAIL, tr("Machine terminated with pending save state!"));12498 }12499 else if (!mConsoleTaskData.mSnapshot.isNull())12500 {12501 LogWarningThisFunc(("canceling untaken snapshot!\n"));12502 12503 /* delete all differencing hard disks created (this will also attach12504 * their parents back by rolling back mMediaData) */12505 i_rollbackMedia();12506 12507 // delete the saved state file (it might have been already created)12508 // AFTER killing the snapshot so that releaseSavedStateFile() won't12509 // think it's still in use12510 Utf8Str strStateFile = mConsoleTaskData.mSnapshot->i_getStateFilePath();12511 mConsoleTaskData.mSnapshot->uninit();12512 i_releaseSavedStateFile(strStateFile, NULL /* pSnapshotToIgnore */ );12513 }12514 12515 12550 mData->mSession.mPID = NIL_RTPROCESS; 12516 12551 … … 12613 12648 12614 12649 /* reset the rest of session data */ 12650 mData->mSession.mLockType = LockType_Null; 12615 12651 mData->mSession.mMachine.setNull(); 12616 12652 mData->mSession.mState = SessionState_Unlocked; … … 12698 12734 } 12699 12735 12736 //////////////////////////////////////////////////////////////////////////////// 12737 // 12738 // SessionMachine task records 12739 // 12740 //////////////////////////////////////////////////////////////////////////////// 12741 12742 /** 12743 * Task record for saving the machine state. 12744 */ 12745 struct SessionMachine::SaveStateTask 12746 : public Machine::Task 12747 { 12748 SaveStateTask(SessionMachine *m, 12749 Progress *p, 12750 const Utf8Str &t, 12751 Reason_T enmReason, 12752 const Utf8Str &strStateFilePath) 12753 : Task(m, p, t), 12754 m_enmReason(enmReason), 12755 m_strStateFilePath(strStateFilePath) 12756 {} 12757 12758 void handler() 12759 { 12760 ((SessionMachine *)(Machine *)m_pMachine)->i_saveStateHandler(*this); 12761 } 12762 12763 Reason_T m_enmReason; 12764 Utf8Str m_strStateFilePath; 12765 }; 12766 12767 /** 12768 * Task thread implementation for SessionMachine::SaveState(), called from 12769 * SessionMachine::taskHandler(). 12770 * 12771 * @note Locks this object for writing. 12772 * 12773 * @param task 12774 * @return 12775 */ 12776 void SessionMachine::i_saveStateHandler(SaveStateTask &task) 12777 { 12778 LogFlowThisFuncEnter(); 12779 12780 AutoCaller autoCaller(this); 12781 LogFlowThisFunc(("state=%d\n", getObjectState().getState())); 12782 if (FAILED(autoCaller.rc())) 12783 { 12784 /* we might have been uninitialized because the session was accidentally 12785 * closed by the client, so don't assert */ 12786 HRESULT rc = setError(E_FAIL, 12787 tr("The session has been accidentally closed")); 12788 task.m_pProgress->i_notifyComplete(rc); 12789 LogFlowThisFuncLeave(); 12790 return; 12791 } 12792 12793 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 12794 12795 HRESULT rc = S_OK; 12796 12797 try 12798 { 12799 ComPtr<IInternalSessionControl> directControl; 12800 if (mData->mSession.mLockType == LockType_VM) 12801 directControl = mData->mSession.mDirectControl; 12802 if (directControl.isNull()) 12803 throw setError(VBOX_E_INVALID_VM_STATE, 12804 tr("Trying to save state without a running VM")); 12805 alock.release(); 12806 BOOL fSuspendedBySave; 12807 rc = directControl->SaveStateWithReason(task.m_enmReason, task.m_pProgress, Bstr(task.m_strStateFilePath).raw(), task.m_machineStateBackup != MachineState_Paused, &fSuspendedBySave); 12808 Assert(!fSuspendedBySave); 12809 alock.acquire(); 12810 12811 AssertStmt( (SUCCEEDED(rc) && mData->mMachineState == MachineState_Saved) 12812 || (FAILED(rc) && mData->mMachineState == MachineState_Saving), 12813 throw E_FAIL); 12814 12815 if (SUCCEEDED(rc)) 12816 { 12817 mSSData->strStateFilePath = task.m_strStateFilePath; 12818 12819 /* save all VM settings */ 12820 rc = i_saveSettings(NULL); 12821 // no need to check whether VirtualBox.xml needs saving also since 12822 // we can't have a name change pending at this point 12823 } 12824 else 12825 { 12826 // On failure, set the state to the state we had at the beginning. 12827 i_setMachineState(task.m_machineStateBackup); 12828 i_updateMachineStateOnClient(); 12829 12830 // Delete the saved state file (might have been already created). 12831 // No need to check whether this is shared with a snapshot here 12832 // because we certainly created a fresh saved state file here. 12833 RTFileDelete(task.m_strStateFilePath.c_str()); 12834 } 12835 } 12836 catch (HRESULT aRC) { rc = aRC; } 12837 12838 task.m_pProgress->i_notifyComplete(rc); 12839 12840 LogFlowThisFuncLeave(); 12841 } 12842 12700 12843 /** 12701 12844 * @note Locks this object for writing. 12702 12845 */ 12703 HRESULT SessionMachine::setRemoveSavedStateFile(BOOL aRemove) 12846 HRESULT SessionMachine::saveState(ComPtr<IProgress> &aProgress) 12847 { 12848 return i_saveStateWithReason(Reason_Unspecified, aProgress); 12849 } 12850 12851 HRESULT SessionMachine::i_saveStateWithReason(Reason_T aReason, ComPtr<IProgress> &aProgress) 12704 12852 { 12705 12853 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 12706 12854 12707 mRemoveSavedState = RT_BOOL(aRemove); 12708 12709 return S_OK; 12710 } 12855 HRESULT rc = i_checkStateDependency(MutableOrRunningStateDep); 12856 if (FAILED(rc)) return rc; 12857 12858 if ( mData->mMachineState != MachineState_Running 12859 && mData->mMachineState != MachineState_Paused 12860 ) 12861 return setError(VBOX_E_INVALID_VM_STATE, 12862 tr("Cannot save the execution state as the machine is not running or paused (machine state: %s)"), 12863 Global::stringifyMachineState(mData->mMachineState)); 12864 12865 ComObjPtr<Progress> pProgress; 12866 pProgress.createObject(); 12867 rc = pProgress->init(i_getVirtualBox(), 12868 static_cast<IMachine *>(this) /* aInitiator */, 12869 Bstr(tr("Saving the execution state of the virtual machine")).raw(), 12870 FALSE /* aCancelable */); 12871 if (FAILED(rc)) 12872 return rc; 12873 12874 Utf8Str strStateFilePath; 12875 i_composeSavedStateFilename(strStateFilePath); 12876 12877 /* create and start the task on a separate thread (note that it will not 12878 * start working until we release alock) */ 12879 SaveStateTask *pTask = new SaveStateTask(this, pProgress, "SaveState", aReason, strStateFilePath); 12880 rc = pTask->createThread(); 12881 if (FAILED(rc)) 12882 return rc; 12883 12884 /* set the state to Saving (expected by Session::SaveStateWithReason()) */ 12885 i_setMachineState(MachineState_Saving); 12886 i_updateMachineStateOnClient(); 12887 12888 pProgress.queryInterfaceTo(aProgress.asOutParam()); 12889 12890 return S_OK; 12891 } 12892 12893 /** 12894 * @note Locks this object for writing. 12895 */ 12896 HRESULT SessionMachine::adoptSavedState(const com::Utf8Str &aSavedStateFile) 12897 { 12898 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 12899 12900 HRESULT rc = i_checkStateDependency(MutableStateDep); 12901 if (FAILED(rc)) return rc; 12902 12903 if ( mData->mMachineState != MachineState_PoweredOff 12904 && mData->mMachineState != MachineState_Teleported 12905 && mData->mMachineState != MachineState_Aborted 12906 ) 12907 return setError(VBOX_E_INVALID_VM_STATE, 12908 tr("Cannot adopt the saved machine state as the machine is not in Powered Off, Teleported or Aborted state (machine state: %s)"), 12909 Global::stringifyMachineState(mData->mMachineState)); 12910 12911 com::Utf8Str stateFilePathFull; 12912 int vrc = i_calculateFullPath(aSavedStateFile, stateFilePathFull); 12913 if (RT_FAILURE(vrc)) 12914 return setError(VBOX_E_FILE_ERROR, 12915 tr("Invalid saved state file path '%s' (%Rrc)"), 12916 aSavedStateFile.c_str(), 12917 vrc); 12918 12919 mSSData->strStateFilePath = stateFilePathFull; 12920 12921 /* The below i_setMachineState() will detect the state transition and will 12922 * update the settings file */ 12923 12924 return i_setMachineState(MachineState_Saved); 12925 } 12926 12927 /** 12928 * @note Locks this object for writing. 12929 */ 12930 HRESULT SessionMachine::discardSavedState(BOOL aFRemoveFile) 12931 { 12932 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 12933 12934 HRESULT rc = i_checkStateDependency(MutableStateDep); 12935 if (FAILED(rc)) return rc; 12936 12937 if (mData->mMachineState != MachineState_Saved) 12938 return setError(VBOX_E_INVALID_VM_STATE, 12939 tr("Cannot delete the machine state as the machine is not in the saved state (machine state: %s)"), 12940 Global::stringifyMachineState(mData->mMachineState)); 12941 12942 mRemoveSavedState = RT_BOOL(aFRemoveFile); 12943 12944 /* 12945 * Saved -> PoweredOff transition will be detected in the SessionMachine 12946 * and properly handled. 12947 */ 12948 rc = i_setMachineState(MachineState_PoweredOff); 12949 return rc; 12950 } 12951 12711 12952 12712 12953 /** … … 13087 13328 } 13088 13329 13089 /**13090 * @note Locks this object for writing.13091 */13092 HRESULT SessionMachine::beginSavingState(ComPtr<IProgress> &aProgress,13093 com::Utf8Str &aStateFilePath)13094 {13095 LogFlowThisFuncEnter();13096 13097 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);13098 13099 AssertReturn( mData->mMachineState == MachineState_Paused13100 && mConsoleTaskData.mLastState == MachineState_Null13101 && mConsoleTaskData.strStateFilePath.isEmpty(),13102 E_FAIL);13103 13104 /* create a progress object to track operation completion */13105 ComObjPtr<Progress> pProgress;13106 pProgress.createObject();13107 pProgress->init(i_getVirtualBox(),13108 static_cast<IMachine *>(this) /* aInitiator */,13109 Bstr(tr("Saving the execution state of the virtual machine")).raw(),13110 FALSE /* aCancelable */);13111 13112 /* stateFilePath is null when the machine is not running */13113 if (mData->mMachineState == MachineState_Paused)13114 i_composeSavedStateFilename(aStateFilePath);13115 13116 /* fill in the console task data */13117 mConsoleTaskData.mLastState = mData->mMachineState;13118 mConsoleTaskData.strStateFilePath = aStateFilePath;13119 mConsoleTaskData.mProgress = pProgress;13120 13121 /* set the state to Saving (this is expected by Console::SaveState()) */13122 i_setMachineState(MachineState_Saving);13123 13124 pProgress.queryInterfaceTo(aProgress.asOutParam());13125 13126 return S_OK;13127 }13128 13129 /**13130 * @note Locks mParent + this object for writing.13131 */13132 HRESULT SessionMachine::endSavingState(LONG aResult,13133 const com::Utf8Str &aErrMsg)13134 {13135 LogFlowThisFunc(("\n"));13136 13137 /* endSavingState() need mParent lock */13138 AutoMultiWriteLock2 alock(mParent, this COMMA_LOCKVAL_SRC_POS);13139 13140 AssertReturn( ( (SUCCEEDED(aResult) && mData->mMachineState == MachineState_Saved)13141 || (FAILED(aResult) && mData->mMachineState == MachineState_Saving))13142 && mConsoleTaskData.mLastState != MachineState_Null13143 && !mConsoleTaskData.strStateFilePath.isEmpty(),13144 E_FAIL);13145 13146 /*13147 * On failure, set the state to the state we had when BeginSavingState()13148 * was called (this is expected by Console::SaveState() and the associated13149 * task). On success the VM process already changed the state to13150 * MachineState_Saved, so no need to do anything.13151 */13152 if (FAILED(aResult))13153 i_setMachineState(mConsoleTaskData.mLastState);13154 13155 return i_endSavingState(aResult, aErrMsg);13156 }13157 13158 /**13159 * @note Locks this object for writing.13160 */13161 HRESULT SessionMachine::adoptSavedState(const com::Utf8Str &aSavedStateFile)13162 {13163 LogFlowThisFunc(("\n"));13164 13165 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);13166 13167 AssertReturn( mData->mMachineState == MachineState_PoweredOff13168 || mData->mMachineState == MachineState_Teleported13169 || mData->mMachineState == MachineState_Aborted13170 , E_FAIL); /** @todo setError. */13171 13172 com::Utf8Str stateFilePathFull;13173 int vrc = i_calculateFullPath(aSavedStateFile, stateFilePathFull);13174 if (RT_FAILURE(vrc))13175 return setError(VBOX_E_FILE_ERROR,13176 tr("Invalid saved state file path '%s' (%Rrc)"),13177 aSavedStateFile.c_str(),13178 vrc);13179 13180 mSSData->strStateFilePath = stateFilePathFull;13181 13182 /* The below i_setMachineState() will detect the state transition and will13183 * update the settings file */13184 13185 return i_setMachineState(MachineState_Saved);13186 }13187 13188 13330 HRESULT SessionMachine::pullGuestProperties(std::vector<com::Utf8Str> &aNames, 13189 13331 std::vector<com::Utf8Str> &aValues, … … 13263 13405 case MachineState_Teleporting: 13264 13406 case MachineState_TeleportingPausedVM: 13407 case MachineState_OnlineSnapshotting: 13265 13408 case MachineState_LiveSnapshotting: 13266 13409 case MachineState_DeletingSnapshotOnline: … … 13536 13679 { 13537 13680 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13538 directControl = mData->mSession.mDirectControl; 13681 if (mData->mSession.mLockType == LockType_VM) 13682 directControl = mData->mSession.mDirectControl; 13539 13683 } 13540 13684 … … 13561 13705 { 13562 13706 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13563 directControl = mData->mSession.mDirectControl; 13707 if (mData->mSession.mLockType == LockType_VM) 13708 directControl = mData->mSession.mDirectControl; 13564 13709 } 13565 13710 … … 13589 13734 { 13590 13735 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13591 directControl = mData->mSession.mDirectControl; 13736 if (mData->mSession.mLockType == LockType_VM) 13737 directControl = mData->mSession.mDirectControl; 13592 13738 } 13593 13739 … … 13612 13758 { 13613 13759 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13614 directControl = mData->mSession.mDirectControl; 13760 if (mData->mSession.mLockType == LockType_VM) 13761 directControl = mData->mSession.mDirectControl; 13615 13762 } 13616 13763 … … 13635 13782 { 13636 13783 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13637 directControl = mData->mSession.mDirectControl; 13784 if (mData->mSession.mLockType == LockType_VM) 13785 directControl = mData->mSession.mDirectControl; 13638 13786 } 13639 13787 … … 13658 13806 { 13659 13807 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13660 directControl = mData->mSession.mDirectControl; 13808 if (mData->mSession.mLockType == LockType_VM) 13809 directControl = mData->mSession.mDirectControl; 13661 13810 } 13662 13811 … … 13681 13830 { 13682 13831 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13683 directControl = mData->mSession.mDirectControl; 13832 if (mData->mSession.mLockType == LockType_VM) 13833 directControl = mData->mSession.mDirectControl; 13684 13834 } 13685 13835 … … 13701 13851 { 13702 13852 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13703 directControl = mData->mSession.mDirectControl; 13853 if (mData->mSession.mLockType == LockType_VM) 13854 directControl = mData->mSession.mDirectControl; 13704 13855 } 13705 13856 … … 13724 13875 { 13725 13876 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13726 directControl = mData->mSession.mDirectControl; 13877 if (mData->mSession.mLockType == LockType_VM) 13878 directControl = mData->mSession.mDirectControl; 13727 13879 } 13728 13880 … … 13747 13899 { 13748 13900 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13749 directControl = mData->mSession.mDirectControl; 13901 if (mData->mSession.mLockType == LockType_VM) 13902 directControl = mData->mSession.mDirectControl; 13750 13903 } 13751 13904 … … 13770 13923 { 13771 13924 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13772 directControl = mData->mSession.mDirectControl; 13925 if (mData->mSession.mLockType == LockType_VM) 13926 directControl = mData->mSession.mDirectControl; 13773 13927 } 13774 13928 … … 13793 13947 { 13794 13948 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13795 directControl = mData->mSession.mDirectControl; 13949 if (mData->mSession.mLockType == LockType_VM) 13950 directControl = mData->mSession.mDirectControl; 13796 13951 } 13797 13952 … … 13816 13971 { 13817 13972 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13818 directControl = mData->mSession.mDirectControl; 13973 if (mData->mSession.mLockType == LockType_VM) 13974 directControl = mData->mSession.mDirectControl; 13819 13975 } 13820 13976 … … 13839 13995 { 13840 13996 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13841 directControl = mData->mSession.mDirectControl; 13997 if (mData->mSession.mLockType == LockType_VM) 13998 directControl = mData->mSession.mDirectControl; 13842 13999 } 13843 14000 … … 13862 14019 { 13863 14020 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13864 directControl = mData->mSession.mDirectControl; 14021 if (mData->mSession.mLockType == LockType_VM) 14022 directControl = mData->mSession.mDirectControl; 13865 14023 } 13866 14024 … … 13885 14043 { 13886 14044 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13887 directControl = mData->mSession.mDirectControl; 14045 if (mData->mSession.mLockType == LockType_VM) 14046 directControl = mData->mSession.mDirectControl; 13888 14047 } 13889 14048 … … 13951 14110 { 13952 14111 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13953 directControl = mData->mSession.mDirectControl; 14112 if (mData->mSession.mLockType == LockType_VM) 14113 directControl = mData->mSession.mDirectControl; 13954 14114 } 13955 14115 … … 13983 14143 { 13984 14144 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 13985 directControl = mData->mSession.mDirectControl; 14145 if (mData->mSession.mLockType == LockType_VM) 14146 directControl = mData->mSession.mDirectControl; 13986 14147 } 13987 14148 … … 14000 14161 // protected methods 14001 14162 ///////////////////////////////////////////////////////////////////////////// 14002 14003 /**14004 * Helper method to finalize saving the state.14005 *14006 * @note Must be called from under this object's lock.14007 *14008 * @param aRc S_OK if the snapshot has been taken successfully14009 * @param aErrMsg human readable error message for failure14010 *14011 * @note Locks mParent + this objects for writing.14012 */14013 HRESULT SessionMachine::i_endSavingState(HRESULT aRc, const Utf8Str &aErrMsg)14014 {14015 LogFlowThisFuncEnter();14016 14017 AutoCaller autoCaller(this);14018 AssertComRCReturn(autoCaller.rc(), autoCaller.rc());14019 14020 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);14021 14022 HRESULT rc = S_OK;14023 14024 if (SUCCEEDED(aRc))14025 {14026 mSSData->strStateFilePath = mConsoleTaskData.strStateFilePath;14027 14028 /* save all VM settings */14029 rc = i_saveSettings(NULL);14030 // no need to check whether VirtualBox.xml needs saving also since14031 // we can't have a name change pending at this point14032 }14033 else14034 {14035 // delete the saved state file (it might have been already created);14036 // we need not check whether this is shared with a snapshot here because14037 // we certainly created this saved state file here anew14038 RTFileDelete(mConsoleTaskData.strStateFilePath.c_str());14039 }14040 14041 /* notify the progress object about operation completion */14042 Assert(mConsoleTaskData.mProgress);14043 if (SUCCEEDED(aRc))14044 mConsoleTaskData.mProgress->i_notifyComplete(S_OK);14045 else14046 {14047 if (aErrMsg.length())14048 mConsoleTaskData.mProgress->i_notifyComplete(aRc,14049 COM_IIDOF(ISession),14050 getComponentName(),14051 aErrMsg.c_str());14052 else14053 mConsoleTaskData.mProgress->i_notifyComplete(aRc);14054 }14055 14056 /* clear out the temporary saved state data */14057 mConsoleTaskData.mLastState = MachineState_Null;14058 mConsoleTaskData.strStateFilePath.setNull();14059 mConsoleTaskData.mProgress.setNull();14060 14061 LogFlowThisFuncLeave();14062 return rc;14063 }14064 14163 14065 14164 /** … … 14259 14358 || oldMachineState == MachineState_Paused 14260 14359 || oldMachineState == MachineState_Teleporting 14360 || oldMachineState == MachineState_OnlineSnapshotting 14261 14361 || oldMachineState == MachineState_LiveSnapshotting 14262 14362 || oldMachineState == MachineState_Stuck … … 14273 14373 || aMachineState == MachineState_Aborted 14274 14374 ) 14275 /* ignore PoweredOff->Saving->PoweredOff transition when taking a14276 * snapshot */14277 && ( mConsoleTaskData.mSnapshot.isNull()14278 || mConsoleTaskData.mLastState >= MachineState_Running /** @todo Live Migration: clean up (lazy bird) */14279 )14280 14375 ) 14281 14376 { … … 14310 14405 { 14311 14406 /* 14312 * delete the saved state after Console::ForgetSavedState() is called14407 * delete the saved state after SessionMachine::ForgetSavedState() is called 14313 14408 * or if the VM process (owning a direct VM session) crashed while the 14314 14409 * VM was Saved … … 14456 14551 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 14457 14552 AssertReturn(!!mData, E_FAIL); 14458 directControl = mData->mSession.mDirectControl; 14553 if (mData->mSession.mLockType == LockType_VM) 14554 directControl = mData->mSession.mDirectControl; 14459 14555 14460 14556 /* directControl may be already set to NULL here in #OnSessionEnd() … … 14469 14565 if (mData->mSession.mState == SessionState_Unlocking) 14470 14566 return S_OK; 14471 14472 AssertReturn(!directControl.isNull(), E_FAIL); 14473 } 14567 } 14568 14569 /* ignore notifications sent after #OnSessionEnd() is called */ 14570 if (!directControl) 14571 return S_OK; 14474 14572 14475 14573 return directControl->UpdateMachineState(mData->mMachineState); 14476 14574 } 14477 14575 14478 HRESULT Machine::setRemoveSavedStateFile(BOOL aRemove) 14479 { 14480 NOREF(aRemove); 14481 ReturnComNotImplemented(); 14482 } 14576 14577 /** 14578 * Static Machine method that can get passed to RTThreadCreate to 14579 * have a thread started for a Task. See Machine::Task. 14580 */ 14581 /* static */ DECLCALLBACK(int) Machine::taskHandler(RTTHREAD /* thread */, void *pvUser) 14582 { 14583 AssertReturn(pvUser, VERR_INVALID_POINTER); 14584 14585 Task *pTask = static_cast<Task *>(pvUser); 14586 pTask->handler(); 14587 /** @todo r=klaus it would be safer to update the progress object here, 14588 * as it avoids possible races due to scoping issues/tricks in the handler */ 14589 // it's our responsibility to delete the task 14590 delete pTask; 14591 14592 return 0; 14593 } 14594 14595 /*static*/ 14596 HRESULT Machine::i_setErrorStatic(HRESULT aResultCode, const char *pcszMsg, ...) 14597 { 14598 va_list args; 14599 va_start(args, pcszMsg); 14600 HRESULT rc = setErrorInternal(aResultCode, 14601 getStaticClassIID(), 14602 getStaticComponentName(), 14603 Utf8Str(pcszMsg, args), 14604 false /* aWarning */, 14605 true /* aLogIt */); 14606 va_end(args); 14607 return rc; 14608 } 14609 14483 14610 14484 14611 HRESULT Machine::updateState(MachineState_T aState) … … 14558 14685 } 14559 14686 14560 HRESULT Machine::beginSavingState(ComPtr<IProgress> &aProgress,14561 com::Utf8Str &aStateFilePath)14562 {14563 NOREF(aProgress);14564 NOREF(aStateFilePath);14565 ReturnComNotImplemented();14566 }14567 14568 HRESULT Machine::endSavingState(LONG aResult,14569 const com::Utf8Str &aErrMsg)14570 {14571 NOREF(aResult);14572 NOREF(aErrMsg);14573 ReturnComNotImplemented();14574 }14575 14576 HRESULT Machine::adoptSavedState(const com::Utf8Str &aSavedStateFile)14577 {14578 NOREF(aSavedStateFile);14579 ReturnComNotImplemented();14580 }14581 14582 HRESULT Machine::beginTakingSnapshot(const ComPtr<IConsole> &aInitiator,14583 const com::Utf8Str &aName,14584 const com::Utf8Str &aDescription,14585 const ComPtr<IProgress> &aConsoleProgress,14586 BOOL aFTakingSnapshotOnline,14587 com::Utf8Str &aStateFilePath)14588 {14589 NOREF(aInitiator);14590 NOREF(aName);14591 NOREF(aDescription);14592 NOREF(aConsoleProgress);14593 NOREF(aFTakingSnapshotOnline);14594 NOREF(aStateFilePath);14595 ReturnComNotImplemented();14596 }14597 14598 HRESULT Machine::endTakingSnapshot(BOOL aSuccess)14599 {14600 NOREF(aSuccess);14601 ReturnComNotImplemented();14602 }14603 14604 HRESULT Machine::deleteSnapshot(const ComPtr<IConsole> &aInitiator,14605 const com::Guid &aStartId,14606 const com::Guid &aEndId,14607 BOOL aDeleteAllChildren,14608 MachineState_T *aMachineState,14609 ComPtr<IProgress> &aProgress)14610 {14611 NOREF(aInitiator);14612 NOREF(aStartId);14613 NOREF(aEndId);14614 NOREF(aDeleteAllChildren);14615 NOREF(aMachineState);14616 NOREF(aProgress);14617 ReturnComNotImplemented();14618 }14619 14620 14687 HRESULT Machine::finishOnlineMergeMedium() 14621 14688 { 14622 ReturnComNotImplemented();14623 }14624 14625 HRESULT Machine::restoreSnapshot(const ComPtr<IConsole> &aInitiator,14626 const ComPtr<ISnapshot> &aSnapshot,14627 MachineState_T *aMachineState,14628 ComPtr<IProgress> &aProgress)14629 {14630 NOREF(aInitiator);14631 NOREF(aSnapshot);14632 NOREF(aMachineState);14633 NOREF(aProgress);14634 14689 ReturnComNotImplemented(); 14635 14690 } -
trunk/src/VBox/Main/src-server/Performance.cpp
r51498 r55214 5 5 6 6 /* 7 * Copyright (C) 2008-201 4Oracle Corporation7 * Copyright (C) 2008-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 311 311 312 312 /* get the associated console; this is a remote call (!) */ 313 ret = directControl-> GetRemoteConsole(mConsole.asOutParam());313 ret = directControl->COMGETTER(RemoteConsole)(mConsole.asOutParam()); 314 314 if (ret != S_OK) 315 315 return ret; -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r54948 r55214 412 412 } 413 413 414 HRESULT Snapshot::getChildrenCount(ULONG *count)414 HRESULT Snapshot::getChildrenCount(ULONG *count) 415 415 { 416 416 *count = i_getChildrenCount(); … … 1305 1305 1306 1306 /** 1307 * Abstract base class for SessionMachine::RestoreSnapshotTask and 1308 * SessionMachine::DeleteSnapshotTask. This is necessary since 1309 * RTThreadCreate cannot call a method as its thread function, so 1310 * instead we have it call the static SessionMachine::taskHandler, 1311 * which can then call the handler() method in here (implemented 1312 * by the children). 1307 * Still abstract base class for SessionMachine::TakeSnapshotTask, 1308 * SessionMachine::RestoreSnapshotTask and SessionMachine::DeleteSnapshotTask. 1313 1309 */ 1314 1310 struct SessionMachine::SnapshotTask 1311 : public SessionMachine::Task 1315 1312 { 1316 1313 SnapshotTask(SessionMachine *m, 1317 1314 Progress *p, 1315 const Utf8Str &t, 1318 1316 Snapshot *s) 1319 : pMachine(m), 1320 pProgress(p), 1321 machineStateBackup(m->mData->mMachineState), // save the current machine state 1322 pSnapshot(s) 1317 : Task(m, p, t), 1318 m_pSnapshot(s) 1323 1319 {} 1324 1320 1325 void modifyBackedUpState(MachineState_T s) 1326 { 1327 *const_cast<MachineState_T*>(&machineStateBackup) = s; 1328 } 1329 1330 virtual void handler() = 0; 1331 1332 ComObjPtr<SessionMachine> pMachine; 1333 ComObjPtr<Progress> pProgress; 1334 const MachineState_T machineStateBackup; 1335 ComObjPtr<Snapshot> pSnapshot; 1321 ComObjPtr<Snapshot> m_pSnapshot; 1336 1322 }; 1337 1323 1338 /** Restore snapshot state task */ 1324 /** Take snapshot task */ 1325 struct SessionMachine::TakeSnapshotTask 1326 : public SessionMachine::SnapshotTask 1327 { 1328 TakeSnapshotTask(SessionMachine *m, 1329 Progress *p, 1330 const Utf8Str &t, 1331 Snapshot *s, 1332 const Utf8Str &strName, 1333 const Utf8Str &strDescription, 1334 bool fPause, 1335 uint32_t uMemSize, 1336 bool fTakingSnapshotOnline) 1337 : SnapshotTask(m, p, t, s), 1338 m_strName(strName), 1339 m_strDescription(strDescription), 1340 m_fPause(fPause), 1341 m_uMemSize(uMemSize), 1342 m_fTakingSnapshotOnline(fTakingSnapshotOnline) 1343 { 1344 if (fTakingSnapshotOnline) 1345 m_pDirectControl = m->mData->mSession.mDirectControl; 1346 } 1347 1348 void handler() 1349 { 1350 ((SessionMachine *)(Machine *)m_pMachine)->i_takeSnapshotHandler(*this); 1351 } 1352 1353 Utf8Str m_strName; 1354 Utf8Str m_strDescription; 1355 Utf8Str m_strStateFilePath; 1356 ComPtr<IInternalSessionControl> m_pDirectControl; 1357 bool m_fPause; 1358 uint32_t m_uMemSize; 1359 bool m_fTakingSnapshotOnline; 1360 }; 1361 1362 /** Restore snapshot task */ 1339 1363 struct SessionMachine::RestoreSnapshotTask 1340 1364 : public SessionMachine::SnapshotTask … … 1342 1366 RestoreSnapshotTask(SessionMachine *m, 1343 1367 Progress *p, 1368 const Utf8Str &t, 1344 1369 Snapshot *s) 1345 : SnapshotTask(m, p, s)1370 : SnapshotTask(m, p, t, s) 1346 1371 {} 1347 1372 1348 1373 void handler() 1349 1374 { 1350 pMachine->i_restoreSnapshotHandler(*this);1375 ((SessionMachine *)(Machine *)m_pMachine)->i_restoreSnapshotHandler(*this); 1351 1376 } 1352 1377 }; … … 1358 1383 DeleteSnapshotTask(SessionMachine *m, 1359 1384 Progress *p, 1385 const Utf8Str &t, 1360 1386 bool fDeleteOnline, 1361 1387 Snapshot *s) 1362 : SnapshotTask(m, p, s),1388 : SnapshotTask(m, p, t, s), 1363 1389 m_fDeleteOnline(fDeleteOnline) 1364 1390 {} … … 1366 1392 void handler() 1367 1393 { 1368 pMachine->i_deleteSnapshotHandler(*this);1394 ((SessionMachine *)(Machine *)m_pMachine)->i_deleteSnapshotHandler(*this); 1369 1395 } 1370 1396 … … 1372 1398 }; 1373 1399 1374 /**1375 * Static SessionMachine method that can get passed to RTThreadCreate to1376 * have a thread started for a SnapshotTask. See SnapshotTask above.1377 *1378 * This calls either RestoreSnapshotTask::handler() or DeleteSnapshotTask::handler().1379 */1380 1381 /* static */ DECLCALLBACK(int) SessionMachine::taskHandler(RTTHREAD /* thread */, void *pvUser)1382 {1383 AssertReturn(pvUser, VERR_INVALID_POINTER);1384 1385 SnapshotTask *task = static_cast<SnapshotTask*>(pvUser);1386 task->handler();1387 1388 // it's our responsibility to delete the task1389 delete task;1390 1391 return 0;1392 }1393 1400 1394 1401 //////////////////////////////////////////////////////////////////////////////// 1395 1402 // 1396 // TakeSnapshot methods ( SessionMachine and related tasks)1403 // TakeSnapshot methods (Machine and related tasks) 1397 1404 // 1398 1405 //////////////////////////////////////////////////////////////////////////////// 1399 1406 1400 /** 1401 * Implementation for IInternalMachineControl::beginTakingSnapshot(). 1402 * 1403 * Gets called indirectly from Console::TakeSnapshot, which creates a 1404 * progress object in the client and then starts a thread 1405 * (Console::fntTakeSnapshotWorker) which then calls this. 1406 * 1407 * In other words, the asynchronous work for taking snapshots takes place 1408 * on the _client_ (in the Console). This is different from restoring 1409 * or deleting snapshots, which start threads on the server. 1410 * 1411 * This does the server-side work of taking a snapshot: it creates differencing 1412 * images for all hard disks attached to the machine and then creates a 1413 * Snapshot object with a corresponding SnapshotMachine to save the VM settings. 1414 * 1415 * The client's fntTakeSnapshotWorker() blocks while this takes place. 1416 * After this returns successfully, fntTakeSnapshotWorker() will begin 1417 * saving the machine state to the snapshot object and reconfigure the 1418 * hard disks. 1419 * 1420 * When the console is done, it calls SessionMachine::EndTakingSnapshot(). 1421 * 1422 * @note Locks mParent + this object for writing. 1423 * 1424 * @param aInitiator in: The console on which Console::TakeSnapshot was called. 1425 * @param aName in: The name for the new snapshot. 1426 * @param aDescription in: A description for the new snapshot. 1427 * @param aConsoleProgress in: The console's (client's) progress object. 1428 * @param fTakingSnapshotOnline in: True if an online snapshot is being taken (i.e. machine is running). 1429 * @param aStateFilePath out: name of file in snapshots folder to which the console should write the VM state. 1407 HRESULT Machine::takeSnapshot(const com::Utf8Str &aName, 1408 const com::Utf8Str &aDescription, 1409 BOOL fPause, 1410 ComPtr<IProgress> &aProgress) 1411 { 1412 NOREF(aName); 1413 NOREF(aDescription); 1414 NOREF(fPause); 1415 NOREF(aProgress); 1416 ReturnComNotImplemented(); 1417 } 1418 1419 HRESULT SessionMachine::takeSnapshot(const com::Utf8Str &aName, 1420 const com::Utf8Str &aDescription, 1421 BOOL fPause, 1422 ComPtr<IProgress> &aProgress) 1423 { 1424 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1425 LogFlowThisFunc(("aName='%s' mMachineState=%d\n", aName.c_str(), mData->mMachineState)); 1426 1427 if (Global::IsTransient(mData->mMachineState)) 1428 return setError(VBOX_E_INVALID_VM_STATE, 1429 tr("Cannot take a snapshot of the machine while it is changing the state (machine state: %s)"), 1430 Global::stringifyMachineState(mData->mMachineState)); 1431 1432 HRESULT rc = S_OK; 1433 1434 // prepare the progress object: 1435 // a) count the no. of hard disk attachments to get a matching no. of progress sub-operations 1436 ULONG cOperations = 2; // always at least setting up + finishing up 1437 ULONG ulTotalOperationsWeight = 2; // one each for setting up + finishing up 1438 1439 for (MediaData::AttachmentList::iterator it = mMediaData->mAttachments.begin(); 1440 it != mMediaData->mAttachments.end(); 1441 ++it) 1442 { 1443 const ComObjPtr<MediumAttachment> pAtt(*it); 1444 AutoReadLock attlock(pAtt COMMA_LOCKVAL_SRC_POS); 1445 AutoCaller attCaller(pAtt); 1446 if (pAtt->i_getType() == DeviceType_HardDisk) 1447 { 1448 ++cOperations; 1449 1450 // assume that creating a diff image takes as long as saving a 1MB state 1451 ulTotalOperationsWeight += 1; 1452 } 1453 } 1454 1455 // b) one extra sub-operations for online snapshots OR offline snapshots that have a saved state (needs to be copied) 1456 const bool fTakingSnapshotOnline = Global::IsOnline(mData->mMachineState); 1457 LogFlowThisFunc(("fTakingSnapshotOnline = %d\n", fTakingSnapshotOnline)); 1458 if (fTakingSnapshotOnline) 1459 { 1460 ++cOperations; 1461 ulTotalOperationsWeight += mHWData->mMemorySize; 1462 } 1463 1464 // finally, create the progress object 1465 ComObjPtr<Progress> pProgress; 1466 pProgress.createObject(); 1467 rc = pProgress->init(mParent, 1468 static_cast<IMachine *>(this), 1469 Bstr(tr("Taking a snapshot of the virtual machine")).raw(), 1470 fTakingSnapshotOnline /* aCancelable */, 1471 cOperations, 1472 ulTotalOperationsWeight, 1473 Bstr(tr("Setting up snapshot operation")).raw(), // first sub-op description 1474 1); // ulFirstOperationWeight 1475 if (FAILED(rc)) 1476 return rc; 1477 1478 /* create and start the task on a separate thread (note that it will not 1479 * start working until we release alock) */ 1480 TakeSnapshotTask *pTask = new TakeSnapshotTask(this, 1481 pProgress, 1482 "TakeSnap", 1483 NULL /* pSnapshot */, 1484 aName, 1485 aDescription, 1486 !!fPause, 1487 mHWData->mMemorySize, 1488 fTakingSnapshotOnline); 1489 rc = pTask->createThread(); 1490 if (FAILED(rc)) 1491 return rc; 1492 1493 /* set the proper machine state (note: after creating a Task instance) */ 1494 if (fTakingSnapshotOnline) 1495 { 1496 if (pTask->m_machineStateBackup != MachineState_Paused && !fPause) 1497 i_setMachineState(MachineState_LiveSnapshotting); 1498 else 1499 i_setMachineState(MachineState_OnlineSnapshotting); 1500 i_updateMachineStateOnClient(); 1501 } 1502 else 1503 i_setMachineState(MachineState_Snapshotting); 1504 1505 pTask->m_pProgress.queryInterfaceTo(aProgress.asOutParam()); 1506 1507 return rc; 1508 } 1509 1510 /** 1511 * Task thread implementation for SessionMachine::TakeSnapshot(), called from 1512 * SessionMachine::taskHandler(). 1513 * 1514 * @note Locks this object for writing. 1515 * 1516 * @param task 1430 1517 * @return 1431 1518 */ 1432 HRESULT SessionMachine::beginTakingSnapshot(const ComPtr<IConsole> &aInitiator, 1433 const com::Utf8Str &aName, 1434 const com::Utf8Str &aDescription, 1435 const ComPtr<IProgress> &aConsoleProgress, 1436 BOOL aFTakingSnapshotOnline, 1437 com::Utf8Str &aStateFilePath) 1438 { 1439 NOREF(aInitiator); 1519 void SessionMachine::i_takeSnapshotHandler(TakeSnapshotTask &task) 1520 { 1440 1521 LogFlowThisFuncEnter(); 1441 1522 1442 LogFlowThisFunc(("aName='%s' aFTakingSnapshotOnline=%RTbool\n", aName.c_str(), aFTakingSnapshotOnline)); 1523 // Taking a snapshot consists of the following: 1524 // 1) creating a Snapshot object with the current state of the machine 1525 // (hardware + storage) 1526 // 2) creating a diff image for each virtual hard disk, into which write 1527 // operations go after the snapshot has been created 1528 // 3) if the machine is online: saving the state of the virtual machine 1529 // (in the VM process) 1530 // 4) reattach the hard disks 1531 // 5) update the various snapshot/machine objects, save settings 1532 1533 HRESULT rc = S_OK; 1534 AutoCaller autoCaller(this); 1535 LogFlowThisFunc(("state=%d\n", getObjectState().getState())); 1536 if (FAILED(autoCaller.rc())) 1537 { 1538 /* we might have been uninitialized because the session was accidentally 1539 * closed by the client, so don't assert */ 1540 rc = setError(E_FAIL, 1541 tr("The session has been accidentally closed")); 1542 task.m_pProgress->i_notifyComplete(rc); 1543 LogFlowThisFuncLeave(); 1544 return; 1545 } 1443 1546 1444 1547 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1445 1548 1446 AssertReturn( !Global::IsOnlineOrTransient(mData->mMachineState) 1447 || mData->mMachineState == MachineState_Running 1448 || mData->mMachineState == MachineState_Paused, E_FAIL); 1449 AssertReturn(mConsoleTaskData.mLastState == MachineState_Null, E_FAIL); 1450 AssertReturn(mConsoleTaskData.mSnapshot.isNull(), E_FAIL); 1451 1452 if ( mData->mCurrentSnapshot 1453 && mData->mCurrentSnapshot->i_getDepth() >= SETTINGS_SNAPSHOT_DEPTH_MAX) 1454 { 1455 1456 return setError(VBOX_E_INVALID_OBJECT_STATE, 1457 tr("Cannot take another snapshot for machine '%s', because it exceeds the maximum snapshot depth limit. Please delete some earlier snapshot which you no longer need"), 1458 mUserData->s.strName.c_str()); 1459 } 1460 1461 if ( !aFTakingSnapshotOnline 1462 && mData->mMachineState != MachineState_Saved 1463 ) 1464 { 1465 /* save all current settings to ensure current changes are committed and 1466 * hard disks are fixed up */ 1467 HRESULT rc = i_saveSettings(NULL); 1549 bool fBeganTakingSnapshot = false; 1550 BOOL fSuspendedBySave = FALSE; 1551 1552 try 1553 { 1554 // @todo: at this point we have to be in the right state!!!! 1555 AssertStmt( !Global::IsOnlineOrTransient(mData->mMachineState) 1556 || mData->mMachineState == MachineState_Snapshotting 1557 || mData->mMachineState == MachineState_OnlineSnapshotting 1558 || mData->mMachineState == MachineState_LiveSnapshotting, throw E_FAIL); 1559 AssertStmt(task.m_machineStateBackup != mData->mMachineState, throw E_FAIL); 1560 AssertStmt(task.m_pSnapshot.isNull(), throw E_FAIL); 1561 1562 if ( mData->mCurrentSnapshot 1563 && mData->mCurrentSnapshot->i_getDepth() >= SETTINGS_SNAPSHOT_DEPTH_MAX) 1564 { 1565 throw setError(VBOX_E_INVALID_OBJECT_STATE, 1566 tr("Cannot take another snapshot for machine '%s', because it exceeds the maximum snapshot depth limit. Please delete some earlier snapshot which you no longer need"), 1567 mUserData->s.strName.c_str()); 1568 } 1569 1570 if ( !task.m_fTakingSnapshotOnline 1571 && mData->mMachineState != MachineState_Saved) 1572 { 1573 /* save settings to ensure current changes are committed and 1574 * hard disks are fixed up */ 1575 rc = i_saveSettings(NULL); 1468 1576 // no need to check for whether VirtualBox.xml needs changing since 1469 1577 // we can't have a machine XML rename pending at this point 1470 if (FAILED(rc)) return rc; 1471 } 1472 1473 /* create an ID for the snapshot */ 1474 Guid snapshotId; 1475 snapshotId.create(); 1476 1477 /* stateFilePath is null when the machine is not online nor saved */ 1478 if (aFTakingSnapshotOnline) 1479 { 1480 Bstr value; 1481 HRESULT rc = GetExtraData(Bstr("VBoxInternal2/ForceTakeSnapshotWithoutState").raw(), 1482 value.asOutParam()); 1483 if (FAILED(rc) || value != "1") 1484 // creating a new online snapshot: we need a fresh saved state file 1485 i_composeSavedStateFilename(aStateFilePath); 1486 } 1487 else if (mData->mMachineState == MachineState_Saved) 1488 // taking an online snapshot from machine in "saved" state: then use existing state file 1489 aStateFilePath = mSSData->strStateFilePath; 1490 1491 if (aStateFilePath.isNotEmpty()) 1492 { 1493 // ensure the directory for the saved state file exists 1494 HRESULT rc = VirtualBox::i_ensureFilePathExists(aStateFilePath, true /* fCreate */); 1495 if (FAILED(rc)) return rc; 1496 } 1497 1498 /* create a snapshot machine object */ 1499 ComObjPtr<SnapshotMachine> snapshotMachine; 1500 snapshotMachine.createObject(); 1501 HRESULT rc = snapshotMachine->init(this, snapshotId.ref(), aStateFilePath); 1502 AssertComRCReturn(rc, rc); 1503 1504 /* create a snapshot object */ 1505 RTTIMESPEC time; 1506 ComObjPtr<Snapshot> pSnapshot; 1507 pSnapshot.createObject(); 1508 rc = pSnapshot->init(mParent, 1509 snapshotId, 1510 aName, 1511 aDescription, 1512 *RTTimeNow(&time), 1513 snapshotMachine, 1514 mData->mCurrentSnapshot); 1515 AssertComRCReturnRC(rc); 1516 1517 /* fill in the snapshot data */ 1518 mConsoleTaskData.mLastState = mData->mMachineState; 1519 mConsoleTaskData.mSnapshot = pSnapshot; 1520 1521 /// @todo in the long run the progress object should be moved to 1522 // VBoxSVC to avoid trouble with monitoring the progress object state 1523 // when the process where it lives is terminating shortly after the 1524 // operation completed. 1525 1526 try 1527 { 1578 if (FAILED(rc)) 1579 throw rc; 1580 } 1581 1582 /* task.m_strStateFilePath is "" when the machine is offline or saved */ 1583 if (task.m_fTakingSnapshotOnline) 1584 { 1585 Bstr value; 1586 HRESULT rc = GetExtraData(Bstr("VBoxInternal2/ForceTakeSnapshotWithoutState").raw(), 1587 value.asOutParam()); 1588 if (FAILED(rc) || value != "1") 1589 // creating a new online snapshot: we need a fresh saved state file 1590 i_composeSavedStateFilename(task.m_strStateFilePath); 1591 } 1592 else if (mData->mMachineState == MachineState_Saved) 1593 // taking an offline snapshot from machine in "saved" state: use existing state file 1594 task.m_strStateFilePath = mSSData->strStateFilePath; 1595 1596 if (task.m_strStateFilePath.isNotEmpty()) 1597 { 1598 // ensure the directory for the saved state file exists 1599 rc = VirtualBox::i_ensureFilePathExists(task.m_strStateFilePath, true /* fCreate */); 1600 if (FAILED(rc)) 1601 throw rc; 1602 } 1603 1604 /* STEP 1: create the snapshot object */ 1605 1606 /* create an ID for the snapshot */ 1607 Guid snapshotId; 1608 snapshotId.create(); 1609 1610 /* create a snapshot machine object */ 1611 ComObjPtr<SnapshotMachine> pSnapshotMachine; 1612 pSnapshotMachine.createObject(); 1613 rc = pSnapshotMachine->init(this, snapshotId.ref(), task.m_strStateFilePath); 1614 AssertComRCThrowRC(rc); 1615 1616 /* create a snapshot object */ 1617 RTTIMESPEC time; 1618 RTTimeNow(&time); 1619 task.m_pSnapshot.createObject(); 1620 rc = task.m_pSnapshot->init(mParent, 1621 snapshotId, 1622 task.m_strName, 1623 task.m_strDescription, 1624 time, 1625 pSnapshotMachine, 1626 mData->mCurrentSnapshot); 1627 AssertComRCThrowRC(rc); 1628 1629 /* STEP 2: create the diff images */ 1528 1630 LogFlowThisFunc(("Creating differencing hard disks (online=%d)...\n", 1529 aFTakingSnapshotOnline));1530 1531 // backup the media data so we can recover if things goes wrong along the day;1532 // the matching commit() is in fixupMedia() during endSnapshot()1631 task.m_fTakingSnapshotOnline)); 1632 1633 // Backup the media data so we can recover if something goes wrong. 1634 // The matching commit() is in fixupMedia() during SessionMachine::i_finishTakingSnapshot() 1533 1635 i_setModified(IsModified_Storage); 1534 1636 mMediaData.backup(); 1535 1637 1536 /* Console::fntTakeSnapshotWorker and friends expects this. */1537 if (mConsoleTaskData.mLastState == MachineState_Running)1538 i_setMachineState(MachineState_LiveSnapshotting);1539 else1540 i_setMachineState(MachineState_Saving); /** @todo Confusing! Saving is used for both online and offline snapshots. */1541 1542 1638 alock.release(); 1543 1639 /* create new differencing hard disks and attach them to this machine */ 1544 rc = i_createImplicitDiffs( aConsoleProgress,1545 1, // operation weight; must be the same as in Console::TakeSnapshot()1546 !!aFTakingSnapshotOnline);1640 rc = i_createImplicitDiffs(task.m_pProgress, 1641 1, // operation weight; must be the same as in Machine::TakeSnapshot() 1642 task.m_fTakingSnapshotOnline); 1547 1643 if (FAILED(rc)) 1548 1644 throw rc; 1645 alock.acquire(); 1549 1646 1550 1647 // MUST NOT save the settings or the media registry here, because 1551 1648 // this causes trouble with rolling back settings if the user cancels 1552 1649 // taking the snapshot after the diff images have been created. 1553 } 1554 catch (HRESULT hrc) 1555 { 1556 LogThisFunc(("Caught %Rhrc [%s]\n", hrc, Global::stringifyMachineState(mData->mMachineState) )); 1557 if ( mConsoleTaskData.mLastState != mData->mMachineState 1558 && ( mConsoleTaskData.mLastState == MachineState_Running 1559 ? mData->mMachineState == MachineState_LiveSnapshotting 1560 : mData->mMachineState == MachineState_Saving) 1561 ) 1562 i_setMachineState(mConsoleTaskData.mLastState); 1563 1564 pSnapshot->uninit(); 1565 pSnapshot.setNull(); 1566 mConsoleTaskData.mLastState = MachineState_Null; 1567 mConsoleTaskData.mSnapshot.setNull(); 1568 1569 rc = hrc; 1570 1571 // @todo r=dj what with the implicit diff that we created above? this is never cleaned up 1572 } 1573 1574 if (!(aFTakingSnapshotOnline && SUCCEEDED(rc))) 1575 aStateFilePath = ""; 1576 1577 LogFlowThisFunc(("LEAVE - %Rhrc [%s]\n", rc, Global::stringifyMachineState(mData->mMachineState) )); 1578 return rc; 1579 } 1580 1581 /** 1582 * Implementation for IInternalMachineControl::endTakingSnapshot(). 1583 * 1650 1651 fBeganTakingSnapshot = true; 1652 1653 /* Check sanity: for offline snapshots there must not be a saved state 1654 * file name. All other combinations are valid (though online snapshots 1655 * without saved state file seems inconsistent - there are exotic use 1656 * cases, which need to be explicitly enabled, see the code above. */ 1657 if ( !task.m_fTakingSnapshotOnline 1658 && !task.m_strStateFilePath.isEmpty()) 1659 throw setError(E_FAIL, "Invalid state of saved state file"); 1660 1661 // STEP 3: save the VM state (if online) 1662 if (task.m_fTakingSnapshotOnline) 1663 { 1664 task.m_pProgress->SetNextOperation(Bstr(tr("Saving the machine state")).raw(), 1665 mHWData->mMemorySize); // operation weight, same as computed 1666 // when setting up progress object 1667 1668 if (task.m_strStateFilePath.isNotEmpty()) 1669 { 1670 alock.release(); 1671 task.m_pProgress->i_setCancelCallback(i_takeSnapshotProgressCancelCallback, &task); 1672 rc = task.m_pDirectControl->SaveStateWithReason(Reason_Snapshot, 1673 task.m_pProgress, 1674 Bstr(task.m_strStateFilePath).raw(), 1675 task.m_fPause, 1676 &fSuspendedBySave); 1677 task.m_pProgress->i_setCancelCallback(NULL, NULL); 1678 alock.acquire(); 1679 if (FAILED(rc)) 1680 throw rc; 1681 } 1682 else 1683 LogRel(("Machine: skipped saving state as part of online snapshot\n")); 1684 1685 if (!task.m_pProgress->i_notifyPointOfNoReturn()) 1686 throw setError(E_FAIL, tr("Canceled")); 1687 1688 // STEP 4: reattach hard disks 1689 LogFlowThisFunc(("Reattaching new differencing hard disks...\n")); 1690 1691 task.m_pProgress->SetNextOperation(Bstr(tr("Reconfiguring medium attachments")).raw(), 1692 1); // operation weight, same as computed when setting up progress object 1693 1694 com::SafeIfaceArray<IMediumAttachment> atts; 1695 rc = COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(atts)); 1696 if (FAILED(rc)) 1697 throw rc; 1698 1699 alock.release(); 1700 rc = task.m_pDirectControl->ReconfigureMediumAttachments(ComSafeArrayAsInParam(atts)); 1701 alock.acquire(); 1702 if (FAILED(rc)) 1703 throw rc; 1704 } 1705 1706 /* 1707 * Finalize the requested snapshot object. This will reset the 1708 * machine state to the state it had at the beginning. 1709 */ 1710 rc = i_finishTakingSnapshot(task, alock, true /*aSuccess*/); 1711 // do not throw rc here because we can't call i_finishTakingSnapshot() twice 1712 LogFlowThisFunc(("i_finishTakingSnapshot -> %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(mData->mMachineState))); 1713 } 1714 catch (HRESULT rcThrown) 1715 { 1716 rc = rcThrown; 1717 LogThisFunc(("Caught %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(mData->mMachineState))); 1718 1719 // @todo r=klaus check that the implicit diffs created above are cleaned up im the relevant error cases 1720 1721 /* preserve existing error info */ 1722 ErrorInfoKeeper eik; 1723 1724 if (fBeganTakingSnapshot) 1725 i_finishTakingSnapshot(task, alock, false /*aSuccess*/); 1726 1727 // have to postpone this to the end as i_finishTakingSnapshot() needs 1728 // it for various cleanup steps 1729 task.m_pSnapshot->uninit(); 1730 task.m_pSnapshot.setNull(); 1731 } 1732 Assert(alock.isWriteLockOnCurrentThread()); 1733 1734 { 1735 // Keep all error information over the cleanup steps 1736 ErrorInfoKeeper eik; 1737 1738 /* 1739 * Fix up the machine state. 1740 * 1741 * For offline snapshots we just update the local copy, for the other 1742 * variants do the entire work. This ensures that the state is in sync 1743 * with the VM process (in particular the VM execution state). 1744 */ 1745 bool fNeedClientMachineStateUpdate = false; 1746 if ( mData->mMachineState == MachineState_LiveSnapshotting 1747 || mData->mMachineState == MachineState_OnlineSnapshotting 1748 || mData->mMachineState == MachineState_Snapshotting) 1749 { 1750 if (!task.m_fTakingSnapshotOnline) 1751 i_setMachineState(task.m_machineStateBackup); 1752 else 1753 { 1754 MachineState_T enmMachineState = MachineState_Null; 1755 HRESULT rc2 = task.m_pDirectControl->COMGETTER(NominalState)(&enmMachineState); 1756 if (FAILED(rc2) || enmMachineState == MachineState_Null) 1757 { 1758 AssertMsgFailed(("state=%s\n", Global::stringifyMachineState(enmMachineState))); 1759 // pure nonsense, try to continue somehow 1760 enmMachineState = MachineState_Aborted; 1761 } 1762 if (enmMachineState == MachineState_Paused) 1763 { 1764 if (fSuspendedBySave) 1765 { 1766 alock.release(); 1767 rc2 = task.m_pDirectControl->ResumeWithReason(Reason_Snapshot); 1768 alock.acquire(); 1769 if (SUCCEEDED(rc2)) 1770 enmMachineState = task.m_machineStateBackup; 1771 } 1772 else 1773 enmMachineState = task.m_machineStateBackup; 1774 } 1775 if (enmMachineState != mData->mMachineState) 1776 { 1777 fNeedClientMachineStateUpdate = true; 1778 i_setMachineState(enmMachineState); 1779 } 1780 } 1781 } 1782 1783 /* check the remote state to see that we got it right. */ 1784 MachineState_T enmMachineState = MachineState_Null; 1785 if (!task.m_pDirectControl.isNull()) 1786 { 1787 ComPtr<IConsole> pConsole; 1788 task.m_pDirectControl->COMGETTER(RemoteConsole)(pConsole.asOutParam()); 1789 if (!pConsole.isNull()) 1790 pConsole->COMGETTER(State)(&enmMachineState); 1791 } 1792 LogFlowThisFunc(("local mMachineState=%s remote mMachineState=%s\n", 1793 Global::stringifyMachineState(mData->mMachineState), 1794 Global::stringifyMachineState(enmMachineState))); 1795 1796 if (fNeedClientMachineStateUpdate) 1797 i_updateMachineStateOnClient(); 1798 } 1799 1800 task.m_pProgress->i_notifyComplete(rc); 1801 1802 LogFlowThisFuncLeave(); 1803 } 1804 1805 1806 /** 1807 * Progress cancelation callback employed by SessionMachine::i_takeSnapshotHandler. 1808 */ 1809 /*static*/ 1810 void SessionMachine::i_takeSnapshotProgressCancelCallback(void *pvUser) 1811 { 1812 TakeSnapshotTask *pTask = (TakeSnapshotTask *)pvUser; 1813 AssertPtrReturnVoid(pTask); 1814 AssertReturnVoid(!pTask->m_pDirectControl.isNull()); 1815 pTask->m_pDirectControl->CancelSaveStateWithReason(); 1816 } 1817 1818 1819 /** 1584 1820 * Called by the Console when it's done saving the VM state into the snapshot 1585 1821 * (if online) and reconfiguring the hard disks. See BeginTakingSnapshot() above. … … 1593 1829 * @return 1594 1830 */ 1595 HRESULT SessionMachine:: endTakingSnapshot(BOOLaSuccess)1831 HRESULT SessionMachine::i_finishTakingSnapshot(TakeSnapshotTask &task, AutoWriteLock &alock, bool aSuccess) 1596 1832 { 1597 1833 LogFlowThisFunc(("\n")); 1598 1834 1599 A utoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS);1835 Assert(alock.isWriteLockOnCurrentThread()); 1600 1836 1601 1837 AssertReturn( !aSuccess 1602 || ( ( mData->mMachineState == MachineState_Saving 1603 || mData->mMachineState == MachineState_LiveSnapshotting) 1604 && mConsoleTaskData.mLastState != MachineState_Null 1605 && !mConsoleTaskData.mSnapshot.isNull() 1606 ) 1607 , E_FAIL); 1608 1609 /* 1610 * Restore the state we had when BeginTakingSnapshot() was called, 1611 * Console::fntTakeSnapshotWorker restores its local copy when we return. 1612 * If the state was Running, then let Console::fntTakeSnapshotWorker do it 1613 * all to avoid races. 1614 */ 1615 if ( mData->mMachineState != mConsoleTaskData.mLastState 1616 && mConsoleTaskData.mLastState != MachineState_Running 1617 ) 1618 i_setMachineState(mConsoleTaskData.mLastState); 1838 || mData->mMachineState == MachineState_Snapshotting 1839 || mData->mMachineState == MachineState_OnlineSnapshotting 1840 || mData->mMachineState == MachineState_LiveSnapshotting, E_FAIL); 1619 1841 1620 1842 ComObjPtr<Snapshot> pOldFirstSnap = mData->mFirstSnapshot; 1621 1843 ComObjPtr<Snapshot> pOldCurrentSnap = mData->mCurrentSnapshot; 1622 1844 1623 bool fOnline = Global::IsOnline( mConsoleTaskData.mLastState);1845 bool fOnline = Global::IsOnline(task.m_machineStateBackup); 1624 1846 1625 1847 HRESULT rc = S_OK; … … 1628 1850 { 1629 1851 // new snapshot becomes the current one 1630 mData->mCurrentSnapshot = mConsoleTaskData.mSnapshot;1852 mData->mCurrentSnapshot = task.m_pSnapshot; 1631 1853 1632 1854 /* memorize the first snapshot if necessary */ … … 1651 1873 /* inform callbacks */ 1652 1874 mParent->i_onSnapshotTaken(mData->mUuid, 1653 mConsoleTaskData.mSnapshot->i_getId());1654 machineLock.release();1875 task.m_pSnapshot->i_getId()); 1876 alock.release(); 1655 1877 } 1656 1878 else … … 1658 1880 /* delete all differencing hard disks created (this will also attach 1659 1881 * their parents back by rolling back mMediaData) */ 1660 machineLock.release();1882 alock.release(); 1661 1883 1662 1884 i_rollbackMedia(); … … 1670 1892 // snapshot means that a new saved state file was created, which we must 1671 1893 // clean up now 1672 RTFileDelete( mConsoleTaskData.mSnapshot->i_getStateFilePath().c_str());1673 machineLock.acquire(); 1674 1675 1676 mConsoleTaskData.mSnapshot->uninit();1677 machineLock.release();1894 RTFileDelete(task.m_pSnapshot->i_getStateFilePath().c_str()); 1895 1896 alock.acquire(); 1897 1898 task.m_pSnapshot->uninit(); 1899 alock.release(); 1678 1900 1679 1901 } 1680 1902 1681 1903 /* clear out the snapshot data */ 1682 mConsoleTaskData.mLastState = MachineState_Null; 1683 mConsoleTaskData.mSnapshot.setNull(); 1684 1685 /* machineLock has been released already */ 1686 1904 task.m_pSnapshot.setNull(); 1905 1906 /* alock has been released already */ 1687 1907 mParent->i_saveModifiedRegistries(); 1908 1909 alock.acquire(); 1688 1910 1689 1911 return rc; … … 1692 1914 //////////////////////////////////////////////////////////////////////////////// 1693 1915 // 1694 // RestoreSnapshot methods ( SessionMachine and related tasks)1916 // RestoreSnapshot methods (Machine and related tasks) 1695 1917 // 1696 1918 //////////////////////////////////////////////////////////////////////////////// 1697 1919 1698 /** 1699 * Implementation for IInternalMachineControl::restoreSnapshot(). 1700 * 1701 * Gets called from Console::RestoreSnapshot(), and that's basically the 1702 * only thing Console does. Restoring a snapshot happens entirely on the 1703 * server side since the machine cannot be running. 1704 * 1705 * This creates a new thread that does the work and returns a progress 1706 * object to the client which is then returned to the caller of 1707 * Console::RestoreSnapshot(). 1708 * 1920 HRESULT Machine::restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, 1921 ComPtr<IProgress> &aProgress) 1922 { 1923 NOREF(aSnapshot); 1924 NOREF(aProgress); 1925 ReturnComNotImplemented(); 1926 } 1927 1928 /** 1929 * Restoring a snapshot happens entirely on the server side, the machine cannot be running. 1930 * 1931 * This creates a new thread that does the work and returns a progress object to the client. 1709 1932 * Actual work then takes place in RestoreSnapshotTask::handler(). 1710 1933 * 1711 1934 * @note Locks this + children objects for writing! 1712 1935 * 1713 * @param aInitiator in: rhe console on which Console::RestoreSnapshot was called.1714 1936 * @param aSnapshot in: the snapshot to restore. 1715 * @param aMachineState in: client-side machine state.1716 1937 * @param aProgress out: progress object to monitor restore thread. 1717 1938 * @return 1718 1939 */ 1719 HRESULT SessionMachine::restoreSnapshot(const ComPtr<IConsole> &aInitiator, 1720 const ComPtr<ISnapshot> &aSnapshot, 1721 MachineState_T *aMachineState, 1940 HRESULT SessionMachine::restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, 1722 1941 ComPtr<IProgress> &aProgress) 1723 1942 { … … 1727 1946 1728 1947 // machine must not be running 1729 ComAssertRet(!Global::IsOnlineOrTransient(mData->mMachineState), 1730 E_FAIL); 1948 if (Global::IsOnlineOrTransient(mData->mMachineState)) 1949 return setError(VBOX_E_INVALID_VM_STATE, 1950 tr("Cannot delete the current state of the running machine (machine state: %s)"), 1951 Global::stringifyMachineState(mData->mMachineState)); 1731 1952 1732 1953 ISnapshot* iSnapshot = aSnapshot; 1733 1954 ComObjPtr<Snapshot> pSnapshot(static_cast<Snapshot*>(iSnapshot)); 1734 1955 ComObjPtr<SnapshotMachine> pSnapMachine = pSnapshot->i_getSnapshotMachine(); 1956 1957 HRESULT rc = S_OK; 1735 1958 1736 1959 // create a progress object. The number of operations is: … … 1758 1981 ComObjPtr<Progress> pProgress; 1759 1982 pProgress.createObject(); 1760 pProgress->init(mParent, aInitiator,1983 pProgress->init(mParent, static_cast<IMachine*>(this), 1761 1984 BstrFmt(tr("Restoring snapshot '%s'"), pSnapshot->i_getName().c_str()).raw(), 1762 1985 FALSE /* aCancelable */, … … 1768 1991 /* create and start the task on a separate thread (note that it will not 1769 1992 * start working until we release alock) */ 1770 RestoreSnapshotTask *task = new RestoreSnapshotTask(this, 1771 pProgress, 1772 pSnapshot); 1773 int vrc = RTThreadCreate(NULL, 1774 taskHandler, 1775 (void*)task, 1776 0, 1777 RTTHREADTYPE_MAIN_WORKER, 1778 0, 1779 "RestoreSnap"); 1780 if (RT_FAILURE(vrc)) 1781 { 1782 delete task; 1783 ComAssertRCRet(vrc, E_FAIL); 1784 } 1993 RestoreSnapshotTask *pTask = new RestoreSnapshotTask(this, 1994 pProgress, 1995 "RestoreSnap", 1996 pSnapshot); 1997 rc = pTask->createThread(); 1998 if (FAILED(rc)) 1999 return rc; 1785 2000 1786 2001 /* set the proper machine state (note: after creating a Task instance) */ … … 1789 2004 /* return the progress to the caller */ 1790 2005 pProgress.queryInterfaceTo(aProgress.asOutParam()); 1791 1792 /* return the new state to the caller */1793 *aMachineState = mData->mMachineState;1794 2006 1795 2007 LogFlowThisFuncLeave(); … … 1808 2020 * @note Locks mParent + this object for writing. 1809 2021 * 1810 * @param aTask Task data.1811 */ 1812 void SessionMachine::i_restoreSnapshotHandler(RestoreSnapshotTask & aTask)2022 * @param pTask Task data. 2023 */ 2024 void SessionMachine::i_restoreSnapshotHandler(RestoreSnapshotTask &task) 1813 2025 { 1814 2026 LogFlowThisFuncEnter(); … … 1821 2033 /* we might have been uninitialized because the session was accidentally 1822 2034 * closed by the client, so don't assert */ 1823 aTask.pProgress->i_notifyComplete(E_FAIL,1824 COM_IIDOF(IMachine),1825 getComponentName(),1826 tr("The session has been accidentally closed"));2035 task.m_pProgress->i_notifyComplete(E_FAIL, 2036 COM_IIDOF(IMachine), 2037 getComponentName(), 2038 tr("The session has been accidentally closed")); 1827 2039 1828 2040 LogFlowThisFuncLeave(); … … 1846 2058 /* Delete the saved state file if the machine was Saved prior to this 1847 2059 * operation */ 1848 if ( aTask.machineStateBackup == MachineState_Saved)2060 if (task.m_machineStateBackup == MachineState_Saved) 1849 2061 { 1850 2062 Assert(!mSSData->strStateFilePath.isEmpty()); … … 1856 2068 i_releaseSavedStateFile(strStateFile, NULL /* pSnapshotToIgnore */ ); 1857 2069 1858 aTask.modifyBackedUpState(MachineState_PoweredOff);2070 task.modifyBackedUpState(MachineState_PoweredOff); 1859 2071 1860 2072 rc = i_saveStateSettings(SaveSTS_StateFilePath); … … 1867 2079 1868 2080 { 1869 AutoReadLock snapshotLock( aTask.pSnapshot COMMA_LOCKVAL_SRC_POS);2081 AutoReadLock snapshotLock(task.m_pSnapshot COMMA_LOCKVAL_SRC_POS); 1870 2082 1871 2083 /* remember the timestamp of the snapshot we're restoring from */ 1872 snapshotTimeStamp = aTask.pSnapshot->i_getTimeStamp();1873 1874 ComPtr<SnapshotMachine> pSnapshotMachine( aTask.pSnapshot->i_getSnapshotMachine());2084 snapshotTimeStamp = task.m_pSnapshot->i_getTimeStamp(); 2085 2086 ComPtr<SnapshotMachine> pSnapshotMachine(task.m_pSnapshot->i_getSnapshotMachine()); 1875 2087 1876 2088 /* copy all hardware data from the snapshot */ … … 1897 2109 alock.release(); 1898 2110 1899 rc = i_createImplicitDiffs( aTask.pProgress,2111 rc = i_createImplicitDiffs(task.m_pProgress, 1900 2112 1, 1901 2113 false /* aOnline */); … … 1907 2119 1908 2120 /* Note: on success, current (old) hard disks will be 1909 * deassociated/deleted on #commit() called from # saveSettings() at2121 * deassociated/deleted on #commit() called from #i_saveSettings() at 1910 2122 * the end. On failure, newly created implicit diffs will be 1911 2123 * deleted by #rollback() at the end. */ … … 1914 2126 Assert(mSSData->strStateFilePath.isEmpty()); 1915 2127 1916 const Utf8Str &strSnapshotStateFile = aTask.pSnapshot->i_getStateFilePath();2128 const Utf8Str &strSnapshotStateFile = task.m_pSnapshot->i_getStateFilePath(); 1917 2129 1918 2130 if (strSnapshotStateFile.isNotEmpty()) … … 1920 2132 mSSData->strStateFilePath = strSnapshotStateFile; 1921 2133 1922 LogFlowThisFunc(("Setting new current snapshot {%RTuuid}\n", aTask.pSnapshot->i_getId().raw()));2134 LogFlowThisFunc(("Setting new current snapshot {%RTuuid}\n", task.m_pSnapshot->i_getId().raw())); 1923 2135 /* make the snapshot we restored from the current snapshot */ 1924 mData->mCurrentSnapshot = aTask.pSnapshot;2136 mData->mCurrentSnapshot = task.m_pSnapshot; 1925 2137 } 1926 2138 … … 1969 2181 1970 2182 // detach the current-state diffs that we detected above and build a list of 1971 // image files to delete _after_ saveSettings()2183 // image files to delete _after_ i_saveSettings() 1972 2184 1973 2185 MediaList llDiffsToDelete; … … 1985 2197 1986 2198 // Normally we "detach" the medium by removing the attachment object 1987 // from the current machine data; saveSettings() below would then2199 // from the current machine data; i_saveSettings() below would then 1988 2200 // compare the current machine data with the one in the backup 1989 2201 // and actually call Medium::removeBackReference(). But that works only half … … 1991 2203 // remove from machine data 1992 2204 mMediaData->mAttachments.remove(pAttach); 1993 // Remove it from the backup or else saveSettings will try to detach2205 // Remove it from the backup or else i_saveSettings will try to detach 1994 2206 // it again and assert. The paranoia check avoids crashes (see 1995 2207 // assert above) if this code is buggy and saves settings in the … … 2009 2221 if (FAILED(rc)) 2010 2222 throw rc; 2011 // unconditionally add the parent registry. We do similar in SessionMachine::EndTakingSnapshot2012 // (mParent->saveSettings())2013 2223 2014 2224 // release the locks before updating registry and deleting image files 2015 2225 alock.release(); 2016 2226 2227 // unconditionally add the parent registry. 2017 2228 mParent->i_markRegistryModified(mParent->i_getGlobalRegistryId()); 2018 2229 … … 2028 2239 HRESULT rc2 = pMedium->i_deleteStorage(NULL /* aProgress */, 2029 2240 true /* aWait */); 2030 // ignore errors here because we cannot roll back after saveSettings() above2241 // ignore errors here because we cannot roll back after i_saveSettings() above 2031 2242 if (SUCCEEDED(rc2)) 2032 2243 pMedium->uninit(); … … 2049 2260 { 2050 2261 /* restore the machine state */ 2051 i_setMachineState( aTask.machineStateBackup);2262 i_setMachineState(task.m_machineStateBackup); 2052 2263 i_updateMachineStateOnClient(); 2053 2264 } … … 2057 2268 2058 2269 /* set the result (this will try to fetch current error info on failure) */ 2059 aTask.pProgress->i_notifyComplete(rc);2270 task.m_pProgress->i_notifyComplete(rc); 2060 2271 2061 2272 if (SUCCEEDED(rc)) … … 2073 2284 //////////////////////////////////////////////////////////////////////////////// 2074 2285 2075 /** 2076 * Implementation for IInternalMachineControl::deleteSnapshot(). 2077 * 2078 * Gets called from Console::DeleteSnapshot(), and that's basically the 2079 * only thing Console does initially. Deleting a snapshot happens entirely on 2080 * the server side if the machine is not running, and if it is running then 2081 * the individual merges are done via internal session callbacks. 2286 HRESULT Machine::deleteSnapshot(const com::Guid &aId, ComPtr<IProgress> &aProgress) 2287 { 2288 NOREF(aId); 2289 NOREF(aProgress); 2290 ReturnComNotImplemented(); 2291 } 2292 2293 HRESULT SessionMachine::deleteSnapshot(const com::Guid &aId, ComPtr<IProgress> &aProgress) 2294 { 2295 return i_deleteSnapshot(aId, aId, 2296 FALSE /* fDeleteAllChildren */, 2297 aProgress); 2298 } 2299 2300 HRESULT Machine::deleteSnapshotAndAllChildren(const com::Guid &aId, ComPtr<IProgress> &aProgress) 2301 { 2302 NOREF(aId); 2303 NOREF(aProgress); 2304 ReturnComNotImplemented(); 2305 } 2306 2307 HRESULT SessionMachine::deleteSnapshotAndAllChildren(const com::Guid &aId, ComPtr<IProgress> &aProgress) 2308 { 2309 return i_deleteSnapshot(aId, aId, 2310 TRUE /* fDeleteAllChildren */, 2311 aProgress); 2312 } 2313 2314 HRESULT Machine::deleteSnapshotRange(const com::Guid &aStartId, const com::Guid &aEndId, ComPtr<IProgress> &aProgress) 2315 { 2316 NOREF(aStartId); 2317 NOREF(aEndId); 2318 NOREF(aProgress); 2319 ReturnComNotImplemented(); 2320 } 2321 2322 HRESULT SessionMachine::deleteSnapshotRange(const com::Guid &aStartId, const com::Guid &aEndId, ComPtr<IProgress> &aProgress) 2323 { 2324 return i_deleteSnapshot(aStartId, aEndId, 2325 FALSE /* fDeleteAllChildren */, 2326 aProgress); 2327 } 2328 2329 2330 /** 2331 * Implementation for SessionMachine::i_deleteSnapshot(). 2332 * 2333 * Gets called from SessionMachine::DeleteSnapshot(). Deleting a snapshot 2334 * happens entirely on the server side if the machine is not running, and 2335 * if it is running then the merges are done via internal session callbacks. 2082 2336 * 2083 2337 * This creates a new thread that does the work and returns a progress 2084 * object to the client which is then returned to the caller of 2085 * Console::DeleteSnapshot(). 2086 * 2087 * Actual work then takes place in DeleteSnapshotTask::handler(). 2338 * object to the client. 2339 * 2340 * Actual work then takes place in SessionMachine::i_deleteSnapshotHandler(). 2088 2341 * 2089 2342 * @note Locks mParent + this + children objects for writing! 2090 2343 */ 2091 HRESULT SessionMachine::deleteSnapshot(const ComPtr<IConsole> &aInitiator, 2092 const com::Guid &aStartId, 2093 const com::Guid &aEndId, 2094 BOOL aDeleteAllChildren, 2095 MachineState_T *aMachineState, 2096 ComPtr<IProgress> &aProgress) 2344 HRESULT SessionMachine::i_deleteSnapshot(const com::Guid &aStartId, 2345 const com::Guid &aEndId, 2346 BOOL aDeleteAllChildren, 2347 ComPtr<IProgress> &aProgress) 2097 2348 { 2098 2349 LogFlowThisFuncEnter(); 2099 2350 2100 AssertReturn( aInitiator &&!aStartId.isZero() && !aEndId.isZero() && aStartId.isValid() && aEndId.isValid(), E_INVALIDARG);2351 AssertReturn(!aStartId.isZero() && !aEndId.isZero() && aStartId.isValid() && aEndId.isValid(), E_INVALIDARG); 2101 2352 2102 2353 … … 2106 2357 2107 2358 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2359 2360 if (Global::IsTransient(mData->mMachineState)) 2361 return setError(VBOX_E_INVALID_VM_STATE, 2362 tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"), 2363 Global::stringifyMachineState(mData->mMachineState)); 2108 2364 2109 2365 // be very picky about machine states … … 2200 2456 ComObjPtr<Progress> pProgress; 2201 2457 pProgress.createObject(); 2202 pProgress->init(mParent, aInitiator,2458 pProgress->init(mParent, static_cast<IMachine*>(this), 2203 2459 BstrFmt(tr("Deleting snapshot '%s'"), pSnapshot->i_getName().c_str()).raw(), 2204 2460 FALSE /* aCancelable */, … … 2212 2468 2213 2469 /* create and start the task on a separate thread */ 2214 DeleteSnapshotTask *task = new DeleteSnapshotTask(this, pProgress, 2215 fDeleteOnline, pSnapshot); 2216 int vrc = RTThreadCreate(NULL, 2217 taskHandler, 2218 (void*)task, 2219 0, 2220 RTTHREADTYPE_MAIN_WORKER, 2221 0, 2222 "DeleteSnapshot"); 2223 if (RT_FAILURE(vrc)) 2224 { 2225 delete task; 2226 return E_FAIL; 2227 } 2470 DeleteSnapshotTask *pTask = new DeleteSnapshotTask(this, pProgress, 2471 "DeleteSnap", 2472 fDeleteOnline, 2473 pSnapshot); 2474 rc = pTask->createThread(); 2475 if (FAILED(rc)) 2476 return rc; 2228 2477 2229 2478 // the task might start running but will block on acquiring the machine's write lock … … 2236 2485 else 2237 2486 i_setMachineState(MachineState_DeletingSnapshot); 2487 i_updateMachineStateOnClient(); 2238 2488 2239 2489 /* return the progress to the caller */ 2240 2490 pProgress.queryInterfaceTo(aProgress.asOutParam()); 2241 2242 /* return the new state to the caller */2243 *aMachineState = mData->mMachineState;2244 2491 2245 2492 LogFlowThisFuncLeave(); … … 2341 2588 * @note Locks the machine + the snapshot + the media tree for writing! 2342 2589 * 2343 * @param aTask Task data. 2344 */ 2345 2346 void SessionMachine::i_deleteSnapshotHandler(DeleteSnapshotTask &aTask) 2590 * @param pTask Task data. 2591 */ 2592 void SessionMachine::i_deleteSnapshotHandler(DeleteSnapshotTask &task) 2347 2593 { 2348 2594 LogFlowThisFuncEnter(); 2349 2595 2596 HRESULT rc = S_OK; 2350 2597 AutoCaller autoCaller(this); 2351 2352 2598 LogFlowThisFunc(("state=%d\n", getObjectState().getState())); 2353 if ( !autoCaller.isOk())2599 if (FAILED(autoCaller.rc())) 2354 2600 { 2355 2601 /* we might have been uninitialized because the session was accidentally 2356 2602 * closed by the client, so don't assert */ 2357 aTask.pProgress->i_notifyComplete(E_FAIL, 2358 COM_IIDOF(IMachine), 2359 getComponentName(), 2360 tr("The session has been accidentally closed")); 2603 rc = setError(E_FAIL, 2604 tr("The session has been accidentally closed")); 2605 task.m_pProgress->i_notifyComplete(rc); 2361 2606 LogFlowThisFuncLeave(); 2362 2607 return; 2363 2608 } 2364 2609 2365 HRESULT rc = S_OK;2366 2610 MediumDeleteRecList toDelete; 2367 2611 Guid snapshotId; … … 2371 2615 /* Locking order: */ 2372 2616 AutoMultiWriteLock2 multiLock(this->lockHandle(), // machine 2373 aTask.pSnapshot->lockHandle()// snapshot2617 task.m_pSnapshot->lockHandle() // snapshot 2374 2618 COMMA_LOCKVAL_SRC_POS); 2375 2619 // once we have this lock, we know that SessionMachine::DeleteSnapshot() … … 2379 2623 COMMA_LOCKVAL_SRC_POS); 2380 2624 2381 ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->i_getSnapshotMachine();2625 ComObjPtr<SnapshotMachine> pSnapMachine = task.m_pSnapshot->i_getSnapshotMachine(); 2382 2626 // no need to lock the snapshot machine since it is const by definition 2383 2627 Guid machineId = pSnapMachine->i_getId(); 2384 2628 2385 2629 // save the snapshot ID (for callbacks) 2386 snapshotId = aTask.pSnapshot->i_getId();2630 snapshotId = task.m_pSnapshot->i_getId(); 2387 2631 2388 2632 // first pass: … … 2428 2672 MediumLockList *pChildrenToReparent = NULL; 2429 2673 bool fNeedsOnlineMerge = false; 2430 bool fOnlineMergePossible = aTask.m_fDeleteOnline;2674 bool fOnlineMergePossible = task.m_fDeleteOnline; 2431 2675 MediumLockList *pMediumLockList = NULL; 2432 2676 MediumLockList *pVMMALockList = NULL; … … 2666 2910 AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS); 2667 2911 2668 Utf8Str stateFilePath = aTask.pSnapshot->i_getStateFilePath();2912 Utf8Str stateFilePath = task.m_pSnapshot->i_getStateFilePath(); 2669 2913 if (!stateFilePath.isEmpty()) 2670 2914 { 2671 aTask.pProgress->SetNextOperation(Bstr(tr("Deleting the execution state")).raw(),2672 1); // weight2673 2674 i_releaseSavedStateFile(stateFilePath, aTask.pSnapshot /* pSnapshotToIgnore */);2915 task.m_pProgress->SetNextOperation(Bstr(tr("Deleting the execution state")).raw(), 2916 1); // weight 2917 2918 i_releaseSavedStateFile(stateFilePath, task.m_pSnapshot /* pSnapshotToIgnore */); 2675 2919 2676 2920 // machine will need saving now … … 2697 2941 } 2698 2942 2699 aTask.pProgress->SetNextOperation(BstrFmt(tr("Merging differencing image '%s'"),2700 pMedium->i_getName().c_str()).raw(),2701 ulWeight);2943 task.m_pProgress->SetNextOperation(BstrFmt(tr("Merging differencing image '%s'"), 2944 pMedium->i_getName().c_str()).raw(), 2945 ulWeight); 2702 2946 2703 2947 bool fNeedSourceUninit = false; … … 2722 2966 /* No need to hold the lock any longer. */ 2723 2967 mLock.release(); 2724 rc = pMedium->i_deleteStorage(& aTask.pProgress,2968 rc = pMedium->i_deleteStorage(&task.m_pProgress, 2725 2969 true /* aWait */); 2726 2970 if (FAILED(rc)) … … 2740 2984 // This callback will arrive while onlineMergeMedium is 2741 2985 // still executing, and there can't be two tasks. 2986 /// @todo r=klaus this hack needs to go, and the logic needs to be "unconvoluted", putting SessionMachine in charge of coordinating the reconfig/resume. 2742 2987 mConsoleTaskData.mDeleteSnapshotInfo = (void *)&(*it); 2743 2988 // online medium merge, in the direction decided earlier … … 2749 2994 it->mpChildrenToReparent, 2750 2995 it->mpMediumLockList, 2751 aTask.pProgress,2996 task.m_pProgress, 2752 2997 &fNeedsSave); 2753 2998 mConsoleTaskData.mDeleteSnapshotInfo = NULL; … … 2761 3006 it->mpChildrenToReparent, 2762 3007 it->mpMediumLockList, 2763 & aTask.pProgress,3008 &task.m_pProgress, 2764 3009 true /* aWait */); 2765 3010 } … … 2826 3071 ComObjPtr<Machine> pMachine = this; 2827 3072 Guid childSnapshotId; 2828 ComObjPtr<Snapshot> pChildSnapshot = aTask.pSnapshot->i_getFirstChild();3073 ComObjPtr<Snapshot> pChildSnapshot = task.m_pSnapshot->i_getFirstChild(); 2829 3074 if (pChildSnapshot) 2830 3075 { … … 2871 3116 AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS); 2872 3117 2873 aTask.pSnapshot->i_beginSnapshotDelete();2874 aTask.pSnapshot->uninit();3118 task.m_pSnapshot->i_beginSnapshotDelete(); 3119 task.m_pSnapshot->uninit(); 2875 3120 2876 3121 machineLock.release(); … … 2912 3157 // restore the machine state that was saved when the 2913 3158 // task was started 2914 i_setMachineState( aTask.machineStateBackup);3159 i_setMachineState(task.m_machineStateBackup); 2915 3160 i_updateMachineStateOnClient(); 2916 3161 … … 2919 3164 2920 3165 // report the result (this will try to fetch current error info on failure) 2921 aTask.pProgress->i_notifyComplete(rc);3166 task.m_pProgress->i_notifyComplete(rc); 2922 3167 2923 3168 if (SUCCEEDED(rc)) … … 3061 3306 aSource = aHD; 3062 3307 aTarget = pChild; 3063 LogFlow Func(("Forward merging selected\n"));3308 LogFlowThisFunc(("Forward merging selected\n")); 3064 3309 } 3065 3310 else … … 3067 3312 aSource = pChild; 3068 3313 aTarget = aHD; 3069 LogFlow Func(("Backward merging selected\n"));3314 LogFlowThisFunc(("Backward merging selected\n")); 3070 3315 } 3071 3316 } … … 3580 3825 AssertComRC(rc); 3581 3826 3827 treeLock.release(); 3582 3828 pMedium->uninit(); 3829 treeLock.acquire(); 3583 3830 } 3584 3831 -
trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py
r55084 r55214 2190 2190 2191 2191 Returns True on success. 2192 Returns False on I Console::restoreSnapshot() failure.2192 Returns False on IMachine::restoreSnapshot() failure. 2193 2193 Returns None if the progress object returns failure. 2194 2194 """ 2195 2195 try: 2196 oProgress = self.o.console.restoreSnapshot(oSnapshot); 2197 except: 2198 reporter.logXcpt('IConsole::restoreSnapshot failed on %s' % (self.sName)); 2196 if self.fpApiVer >= 5.0: 2197 oProgress = self.o.machine.restoreSnapshot(oSnapshot); 2198 else: 2199 oProgress = self.o.console.restoreSnapshot(oSnapshot); 2200 except: 2201 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName)); 2199 2202 if fFudgeOnFailure: 2200 2203 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge … … 2216 2219 2217 2220 Returns True on success. 2218 Returns False on IConsole::deleteSnapshot() failure. 2219 """ 2220 try: 2221 oProgressCom = self.o.console.deleteSnapshot(oSnapshot); 2221 Returns False on IMachine::deleteSnapshot() failure. 2222 """ 2223 try: 2224 if self.fpApiVer >= 5.0: 2225 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot); 2226 else: 2227 oProgressCom = self.o.console.deleteSnapshot(oSnapshot); 2222 2228 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot)); 2223 2229 oProgress.wait(cMsTimeout); 2224 2230 oProgress.logResult(); 2225 2231 except: 2226 reporter.logXcpt('I Console::deleteSnapshot failed on %s' % (self.sName));2232 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName)); 2227 2233 if fFudgeOnFailure: 2228 2234 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge … … 2237 2243 2238 2244 Returns True on success. 2239 Returns False on I Console::takeSnapshot() or VM state change failure.2245 Returns False on IMachine::takeSnapshot() or VM state change failure. 2240 2246 """ 2241 2247 try: … … 2243 2249 and self.oVM.state is vboxcon.MachineState_Running: 2244 2250 self.o.console.pause(); 2245 2246 oProgressCom = self.o.console.takeSnapshot(sName, sDescription); 2251 if self.fpApiVer >= 5.0: 2252 oProgressCom = self.o.machine.takeSnapshot(sName, sDescription); 2253 else 2254 oProgressCom = self.o.console.takeSnapshot(sName, sDescription); 2247 2255 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName)); 2248 2256 oProgress.wait(cMsTimeout); 2249 2257 oProgress.logResult(); 2250 2258 except: 2251 reporter.logXcpt('I Console::takeSnapshot failed on %s' % (self.sName));2259 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName)); 2252 2260 if fFudgeOnFailure: 2253 2261 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
Note:
See TracChangeset
for help on using the changeset viewer.

