Changeset 43378 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Sep 20, 2012 8:16:58 PM (12 years ago)
- Location:
- trunk/src/VBox/Frontends/VBoxAutostart
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.cpp
r42732 r43378 99 99 }; 100 100 101 /** Set by the signal handler. */ 102 static volatile bool g_fCanceled = false; 103 104 105 /** 106 * Signal handler that sets g_fCanceled. 107 * 108 * This can be executed on any thread in the process, on Windows it may even be 109 * a thread dedicated to delivering this signal. Do not doing anything 110 * unnecessary here. 111 */ 112 static void showProgressSignalHandler(int iSignal) 113 { 114 NOREF(iSignal); 115 ASMAtomicWriteBool(&g_fCanceled, true); 116 } 117 118 /** 119 * Print out progress on the console. 120 * 121 * This runs the main event queue every now and then to prevent piling up 122 * unhandled things (which doesn't cause real problems, just makes things 123 * react a little slower than in the ideal case). 124 */ 125 DECLHIDDEN(HRESULT) showProgress(ComPtr<IProgress> progress) 126 { 127 using namespace com; 128 129 BOOL fCompleted = FALSE; 130 ULONG ulCurrentPercent = 0; 131 ULONG ulLastPercent = 0; 132 133 ULONG ulLastOperationPercent = (ULONG)-1; 134 135 ULONG ulLastOperation = (ULONG)-1; 136 Bstr bstrOperationDescription; 137 138 EventQueue::getMainEventQueue()->processEventQueue(0); 139 140 ULONG cOperations = 1; 141 HRESULT hrc = progress->COMGETTER(OperationCount)(&cOperations); 142 if (FAILED(hrc)) 143 { 144 RTStrmPrintf(g_pStdErr, "Progress object failure: %Rhrc\n", hrc); 145 RTStrmFlush(g_pStdErr); 146 return hrc; 147 } 148 149 /* 150 * Note: Outputting the progress info to stderr (g_pStdErr) is intentional 151 * to not get intermixed with other (raw) stdout data which might get 152 * written in the meanwhile. 153 */ 154 RTStrmPrintf(g_pStdErr, "0%%..."); 155 RTStrmFlush(g_pStdErr); 156 157 /* setup signal handling if cancelable */ 158 bool fCanceledAlready = false; 159 BOOL fCancelable; 160 hrc = progress->COMGETTER(Cancelable)(&fCancelable); 161 if (FAILED(hrc)) 162 fCancelable = FALSE; 163 if (fCancelable) 164 { 165 signal(SIGINT, showProgressSignalHandler); 166 #ifdef SIGBREAK 167 signal(SIGBREAK, showProgressSignalHandler); 168 #endif 169 } 170 171 hrc = progress->COMGETTER(Completed(&fCompleted)); 172 while (SUCCEEDED(hrc)) 173 { 174 progress->COMGETTER(Percent(&ulCurrentPercent)); 175 176 /* did we cross a 10% mark? */ 177 if (ulCurrentPercent / 10 > ulLastPercent / 10) 178 { 179 /* make sure to also print out missed steps */ 180 for (ULONG curVal = (ulLastPercent / 10) * 10 + 10; curVal <= (ulCurrentPercent / 10) * 10; curVal += 10) 181 { 182 if (curVal < 100) 183 { 184 RTStrmPrintf(g_pStdErr, "%u%%...", curVal); 185 RTStrmFlush(g_pStdErr); 186 } 187 } 188 ulLastPercent = (ulCurrentPercent / 10) * 10; 189 } 190 191 if (fCompleted) 192 break; 193 194 /* process async cancelation */ 195 if (g_fCanceled && !fCanceledAlready) 196 { 197 hrc = progress->Cancel(); 198 if (SUCCEEDED(hrc)) 199 fCanceledAlready = true; 200 else 201 g_fCanceled = false; 202 } 203 204 /* make sure the loop is not too tight */ 205 progress->WaitForCompletion(100); 206 207 EventQueue::getMainEventQueue()->processEventQueue(0); 208 hrc = progress->COMGETTER(Completed(&fCompleted)); 209 } 210 211 /* undo signal handling */ 212 if (fCancelable) 213 { 214 signal(SIGINT, SIG_DFL); 215 #ifdef SIGBREAK 216 signal(SIGBREAK, SIG_DFL); 217 #endif 218 } 219 220 /* complete the line. */ 221 LONG iRc = E_FAIL; 222 hrc = progress->COMGETTER(ResultCode)(&iRc); 223 if (SUCCEEDED(hrc)) 224 { 225 if (SUCCEEDED(iRc)) 226 RTStrmPrintf(g_pStdErr, "100%%\n"); 227 else if (g_fCanceled) 228 RTStrmPrintf(g_pStdErr, "CANCELED\n"); 229 else 230 { 231 RTStrmPrintf(g_pStdErr, "\n"); 232 RTStrmPrintf(g_pStdErr, "Progress state: %Rhrc\n", iRc); 233 } 234 hrc = iRc; 235 } 236 else 237 { 238 RTStrmPrintf(g_pStdErr, "\n"); 239 RTStrmPrintf(g_pStdErr, "Progress object failure: %Rhrc\n", hrc); 240 } 241 RTStrmFlush(g_pStdErr); 242 return hrc; 243 } 244 245 DECLHIDDEN(const char *) machineStateToName(MachineState_T machineState, bool fShort) 246 { 247 switch (machineState) 248 { 249 case MachineState_PoweredOff: 250 return fShort ? "poweroff" : "powered off"; 251 case MachineState_Saved: 252 return "saved"; 253 case MachineState_Aborted: 254 return "aborted"; 255 case MachineState_Teleported: 256 return "teleported"; 257 case MachineState_Running: 258 return "running"; 259 case MachineState_Paused: 260 return "paused"; 261 case MachineState_Stuck: 262 return fShort ? "gurumeditation" : "guru meditation"; 263 case MachineState_LiveSnapshotting: 264 return fShort ? "livesnapshotting" : "live snapshotting"; 265 case MachineState_Teleporting: 266 return "teleporting"; 267 case MachineState_Starting: 268 return "starting"; 269 case MachineState_Stopping: 270 return "stopping"; 271 case MachineState_Saving: 272 return "saving"; 273 case MachineState_Restoring: 274 return "restoring"; 275 case MachineState_TeleportingPausedVM: 276 return fShort ? "teleportingpausedvm" : "teleporting paused vm"; 277 case MachineState_TeleportingIn: 278 return fShort ? "teleportingin" : "teleporting (incoming)"; 279 case MachineState_RestoringSnapshot: 280 return fShort ? "restoringsnapshot" : "restoring snapshot"; 281 case MachineState_DeletingSnapshot: 282 return fShort ? "deletingsnapshot" : "deleting snapshot"; 283 case MachineState_DeletingSnapshotOnline: 284 return fShort ? "deletingsnapshotlive" : "deleting snapshot live"; 285 case MachineState_DeletingSnapshotPaused: 286 return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused"; 287 case MachineState_SettingUp: 288 return fShort ? "settingup" : "setting up"; 289 default: 290 break; 291 } 292 return "unknown"; 293 } 101 294 102 295 DECLHIDDEN(void) serviceLog(const char *pszFormat, ...) -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h
r42732 r43378 113 113 114 114 /** 115 * Print out progress on the console. 116 * 117 * This runs the main event queue every now and then to prevent piling up 118 * unhandled things (which doesn't cause real problems, just makes things 119 * react a little slower than in the ideal case). 120 */ 121 DECLHIDDEN(HRESULT) showProgress(ComPtr<IProgress> progress); 122 123 /** 124 * Converts the machine state to a human readable string. 125 * 126 * @returns Pointer to the human readable state. 127 * @param enmMachineState Machine state to convert. 128 * @param fShort Flag whether to return a short form. 129 */ 130 DECLHIDDEN(const char *) machineStateToName(MachineState_T enmMachineState, bool fShort); 131 132 /** 115 133 * Parse the given configuration file and return the interesting config parameters. 116 134 * -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStop.cpp
r42732 r43378 27 27 #include <iprt/log.h> 28 28 #include <iprt/assert.h> 29 #include <iprt/message.h> 29 30 30 31 #include <algorithm> … … 36 37 using namespace com; 37 38 39 /** 40 * VM list entry. 41 */ 42 typedef struct AUTOSTOPVM 43 { 44 /** ID of the VM to start. */ 45 Bstr strId; 46 /** Action to do with the VM. */ 47 AutostopType_T enmAutostopType; 48 } AUTOSTOPVM; 49 50 static HRESULT autostartSaveVMState(ComPtr<IConsole> &console) 51 { 52 HRESULT rc = S_OK; 53 ComPtr<IProgress> progress; 54 55 do 56 { 57 /* first pause so we don't trigger a live save which needs more time/resources */ 58 bool fPaused = false; 59 rc = console->Pause(); 60 if (FAILED(rc)) 61 { 62 bool fError = true; 63 if (rc == VBOX_E_INVALID_VM_STATE) 64 { 65 /* check if we are already paused */ 66 MachineState_T machineState; 67 CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState)); 68 /* the error code was lost by the previous instruction */ 69 rc = VBOX_E_INVALID_VM_STATE; 70 if (machineState != MachineState_Paused) 71 { 72 RTMsgError("Machine in invalid state %d -- %s\n", 73 machineState, machineStateToName(machineState, false)); 74 } 75 else 76 { 77 fError = false; 78 fPaused = true; 79 } 80 } 81 if (fError) 82 break; 83 } 84 85 CHECK_ERROR(console, SaveState(progress.asOutParam())); 86 if (FAILED(rc)) 87 { 88 if (!fPaused) 89 console->Resume(); 90 break; 91 } 92 93 rc = showProgress(progress); 94 CHECK_PROGRESS_ERROR(progress, ("Failed to save machine state")); 95 if (FAILED(rc)) 96 { 97 if (!fPaused) 98 console->Resume(); 99 } 100 } while (0); 101 102 return rc; 103 } 104 38 105 DECLHIDDEN(RTEXITCODE) autostartStopMain(PCFGAST pCfgAst) 39 106 { 40 107 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 41 42 AssertMsgFailed(("Not implemented yet!\n")); 108 int vrc = VINF_SUCCESS; 109 std::list<AUTOSTOPVM> listVM; 110 111 /* 112 * Build a list of all VMs we need to autostop first, apply the overrides 113 * from the configuration and start the VMs afterwards. 114 */ 115 com::SafeIfaceArray<IMachine> machines; 116 HRESULT rc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines)); 117 if (SUCCEEDED(rc)) 118 { 119 /* 120 * Iterate through the collection and construct a list of machines 121 * we have to check. 122 */ 123 for (size_t i = 0; i < machines.size(); ++i) 124 { 125 if (machines[i]) 126 { 127 BOOL fAccessible; 128 CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible)); 129 if (!fAccessible) 130 continue; 131 132 AutostopType_T enmAutostopType; 133 CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostopType)(&enmAutostopType)); 134 if (enmAutostopType != AutostopType_Disabled) 135 { 136 AUTOSTOPVM autostopVM; 137 138 CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(autostopVM.strId.asOutParam())); 139 autostopVM.enmAutostopType = enmAutostopType; 140 141 listVM.push_back(autostopVM); 142 } 143 } 144 } 145 146 if ( SUCCEEDED(rc) 147 && listVM.size()) 148 { 149 std::list<AUTOSTOPVM>::iterator it; 150 for (it = listVM.begin(); it != listVM.end(); it++) 151 { 152 MachineState_T enmMachineState; 153 ComPtr<IMachine> machine; 154 155 CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine((*it).strId.raw(), 156 machine.asOutParam())); 157 158 CHECK_ERROR_BREAK(machine, COMGETTER(State)(&enmMachineState)); 159 160 /* Only power off running machines. */ 161 /** @todo: What about transient VM states? */ 162 if ( enmMachineState == MachineState_Running 163 || enmMachineState == MachineState_Paused) 164 { 165 ComPtr<IMachine> sessionMachine; 166 ComPtr<IConsole> console; 167 ComPtr<IProgress> progress; 168 169 /* open a session for the VM */ 170 CHECK_ERROR_BREAK(machine, LockMachine(g_pSession, LockType_Shared)); 171 172 /* get the associated console */ 173 CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam())); 174 CHECK_ERROR_BREAK(g_pSession, COMGETTER(Machine)(sessionMachine.asOutParam())); 175 176 switch ((*it).enmAutostopType) 177 { 178 case AutostopType_SaveState: 179 { 180 rc = autostartSaveVMState(console); 181 break; 182 } 183 case AutostopType_PowerOff: 184 { 185 CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam())); 186 187 rc = showProgress(progress); 188 CHECK_PROGRESS_ERROR(progress, ("Failed to power off machine")); 189 break; 190 } 191 case AutostopType_AcpiShutdown: 192 { 193 /** @todo: Wait for VM to change to powered off state. */ 194 BOOL fGuestEnteredACPI = false; 195 CHECK_ERROR_BREAK(console, GetGuestEnteredACPIMode(&fGuestEnteredACPI)); 196 if (fGuestEnteredACPI) 197 CHECK_ERROR_BREAK(console, PowerButton()); 198 else 199 { 200 /* Use save state instead and log this to the console. */ 201 serviceLog("The guest of VM \"%ls\" does not support ACPI shutdown, saving state...\n", 202 (*it).strId.raw()); 203 rc = autostartSaveVMState(console); 204 } 205 break; 206 } 207 default: 208 serviceLog("Unknown autostop type for VM \"%ls\"\n", (*it).strId.raw()); 209 } 210 } 211 g_pSession->UnlockMachine(); 212 } 213 } 214 } 43 215 44 216 return rcExit;
Note:
See TracChangeset
for help on using the changeset viewer.