VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStart.cpp@ 95103

Last change on this file since 95103 was 95103, checked in by vboxsync, 3 years ago

FE/VBoxAutostart: Lots of small cleanups here and there, mostly in the logging and documentation area. Added more syntax help to make more clear how to actually use this binary. Also added support for logging verbosity levels and output those stdout (if available).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* $Id: VBoxAutostartStart.cpp 95103 2022-05-25 14:37:08Z vboxsync $ */
2/** @file
3 * VBoxAutostart - VirtualBox Autostart service, start machines during system boot.
4 */
5
6/*
7 * Copyright (C) 2012-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/com/com.h>
19#include <VBox/com/string.h>
20#include <VBox/com/Guid.h>
21#include <VBox/com/array.h>
22#include <VBox/com/ErrorInfo.h>
23#include <VBox/com/errorprint.h>
24
25#include <iprt/errcore.h>
26#include <iprt/log.h>
27#include <iprt/message.h>
28#include <iprt/stream.h>
29#include <iprt/thread.h>
30
31#include <algorithm>
32#include <list>
33
34#include "VBoxAutostart.h"
35
36extern unsigned g_cVerbosity;
37
38using namespace com;
39
40/**
41 * VM list entry.
42 */
43typedef struct AUTOSTARTVM
44{
45 /** ID of the VM to start. */
46 Bstr strId;
47 /** Startup delay of the VM. */
48 ULONG uStartupDelay;
49} AUTOSTARTVM;
50
51static DECLCALLBACK(bool) autostartVMCmp(const AUTOSTARTVM &vm1, const AUTOSTARTVM &vm2)
52{
53 return vm1.uStartupDelay <= vm2.uStartupDelay;
54}
55
56DECLHIDDEN(RTEXITCODE) autostartStartMain(PCFGAST pCfgAst)
57{
58 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
59 int vrc = VINF_SUCCESS;
60 std::list<AUTOSTARTVM> listVM;
61 uint32_t uStartupDelay = 0;
62
63 pCfgAst = autostartConfigAstGetByName(pCfgAst, "startup_delay");
64 if (pCfgAst)
65 {
66 if (pCfgAst->enmType == CFGASTNODETYPE_KEYVALUE)
67 {
68 vrc = RTStrToUInt32Full(pCfgAst->u.KeyValue.aszValue, 10, &uStartupDelay);
69 if (RT_FAILURE(vrc))
70 return RTMsgErrorExit(RTEXITCODE_FAILURE, "'startup_delay' must be an unsigned number");
71 }
72 }
73
74 if (uStartupDelay)
75 {
76 autostartSvcLogVerbose(1, "Delaying start for %RU32 seconds ...\n", uStartupDelay);
77 vrc = RTThreadSleep(uStartupDelay * 1000);
78 }
79
80 if (vrc == VERR_INTERRUPTED)
81 return RTEXITCODE_SUCCESS;
82
83 /*
84 * Build a list of all VMs we need to autostart first, apply the overrides
85 * from the configuration and start the VMs afterwards.
86 */
87 com::SafeIfaceArray<IMachine> machines;
88 HRESULT rc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines));
89 if (SUCCEEDED(rc))
90 {
91 /*
92 * Iterate through the collection
93 */
94 for (size_t i = 0; i < machines.size(); ++i)
95 {
96 if (machines[i])
97 {
98 BOOL fAccessible;
99 CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible));
100 if (!fAccessible)
101 continue;
102
103 BOOL fAutostart;
104 CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartEnabled)(&fAutostart));
105 if (fAutostart)
106 {
107 AUTOSTARTVM autostartVM;
108
109 CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(autostartVM.strId.asOutParam()));
110 CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartDelay)(&autostartVM.uStartupDelay));
111
112 listVM.push_back(autostartVM);
113 }
114 }
115 }
116
117 /**
118 * @todo r=uwe I'm not reindenting this whole burnt offering
119 * to mistinterpreted Dijkstra's "single exit" commandment
120 * just to add this log, hence a bit of duplicate logic here.
121 */
122 if (SUCCEEDED(rc) && listVM.empty())
123 LogRel(("No VMs configured for autostart\n"));
124
125 if ( SUCCEEDED(rc)
126 && !listVM.empty())
127 {
128 ULONG uDelayCurr = 0;
129
130 /* Sort by startup delay and apply base override. */
131 listVM.sort(autostartVMCmp);
132
133 std::list<AUTOSTARTVM>::iterator it;
134 for (it = listVM.begin(); it != listVM.end(); ++it)
135 {
136 ComPtr<IMachine> machine;
137 ComPtr<IProgress> progress;
138
139 if ((*it).uStartupDelay > uDelayCurr)
140 {
141 autostartSvcLogVerbose(1, "Delaying start of the next VMs for %ul seconds ...\n",
142 (*it).uStartupDelay - uDelayCurr);
143 RTThreadSleep(((*it).uStartupDelay - uDelayCurr) * 1000);
144 uDelayCurr = (*it).uStartupDelay;
145 }
146
147 CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine((*it).strId.raw(),
148 machine.asOutParam()));
149
150 CHECK_ERROR_BREAK(machine, LaunchVMProcess(g_pSession, Bstr("headless").raw(),
151 ComSafeArrayNullInParam(), progress.asOutParam()));
152 if (SUCCEEDED(rc) && !progress.isNull())
153 {
154 autostartSvcLogVerbose(1, "Waiting for VM '%ls' to power on...\n", (*it).strId.raw());
155 CHECK_ERROR(progress, WaitForCompletion(-1));
156 if (SUCCEEDED(rc))
157 {
158 BOOL completed = true;
159 CHECK_ERROR(progress, COMGETTER(Completed)(&completed));
160 if (SUCCEEDED(rc))
161 {
162 ASSERT(completed);
163
164 LONG iRc;
165 CHECK_ERROR(progress, COMGETTER(ResultCode)(&iRc));
166 if (SUCCEEDED(rc))
167 {
168 if (FAILED(iRc))
169 {
170 ProgressErrorInfo info(progress);
171 com::GluePrintErrorInfo(info);
172 }
173 else
174 autostartSvcLogVerbose(1, "VM '%ls' has been successfully started.\n", (*it).strId.raw());
175 }
176 }
177 }
178 }
179 SessionState_T enmSessionState;
180 CHECK_ERROR(g_pSession, COMGETTER(State)(&enmSessionState));
181 if (SUCCEEDED(rc) && enmSessionState == SessionState_Locked)
182 g_pSession->UnlockMachine();
183 }
184 }
185 }
186
187 return rcExit;
188}
189
Note: See TracBrowser for help on using the repository browser.

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