VirtualBox

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

Last change on this file since 67954 was 62493, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1/* $Id: VBoxAutostartStart.cpp 62493 2016-07-22 18:44:18Z vboxsync $ */
2/** @file
3 * VBoxAutostart - VirtualBox Autostart service, start machines during system boot.
4 */
5
6/*
7 * Copyright (C) 2012-2016 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/message.h>
26#include <iprt/thread.h>
27#include <iprt/stream.h>
28#include <iprt/log.h>
29
30#include <algorithm>
31#include <list>
32#include <string>
33
34#include "VBoxAutostart.h"
35
36using namespace com;
37
38/**
39 * VM list entry.
40 */
41typedef struct AUTOSTARTVM
42{
43 /** ID of the VM to start. */
44 Bstr strId;
45 /** Startup delay of the VM. */
46 ULONG uStartupDelay;
47} AUTOSTARTVM;
48
49static DECLCALLBACK(bool) autostartVMCmp(const AUTOSTARTVM &vm1, const AUTOSTARTVM &vm2)
50{
51 return vm1.uStartupDelay <= vm2.uStartupDelay;
52}
53
54DECLHIDDEN(RTEXITCODE) autostartStartMain(PCFGAST pCfgAst)
55{
56 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
57 int vrc = VINF_SUCCESS;
58 std::list<AUTOSTARTVM> listVM;
59 uint32_t uStartupDelay = 0;
60
61 pCfgAst = autostartConfigAstGetByName(pCfgAst, "startup_delay");
62 if (pCfgAst)
63 {
64 if (pCfgAst->enmType == CFGASTNODETYPE_KEYVALUE)
65 {
66 vrc = RTStrToUInt32Full(pCfgAst->u.KeyValue.aszValue, 10, &uStartupDelay);
67 if (RT_FAILURE(vrc))
68 return RTMsgErrorExit(RTEXITCODE_FAILURE, "'startup_delay' must be an unsigned number");
69 }
70 }
71
72 if (uStartupDelay)
73 {
74 autostartSvcLogVerbose("Delay starting for %d seconds ...\n", uStartupDelay);
75 vrc = RTThreadSleep(uStartupDelay * 1000);
76 }
77
78 if (vrc == VERR_INTERRUPTED)
79 return RTEXITCODE_SUCCESS;
80
81 /*
82 * Build a list of all VMs we need to autostart first, apply the overrides
83 * from the configuration and start the VMs afterwards.
84 */
85 com::SafeIfaceArray<IMachine> machines;
86 HRESULT rc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines));
87 if (SUCCEEDED(rc))
88 {
89 /*
90 * Iterate through the collection
91 */
92 for (size_t i = 0; i < machines.size(); ++i)
93 {
94 if (machines[i])
95 {
96 BOOL fAccessible;
97 CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible));
98 if (!fAccessible)
99 continue;
100
101 BOOL fAutostart;
102 CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartEnabled)(&fAutostart));
103 if (fAutostart)
104 {
105 AUTOSTARTVM autostartVM;
106
107 CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(autostartVM.strId.asOutParam()));
108 CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartDelay)(&autostartVM.uStartupDelay));
109
110 listVM.push_back(autostartVM);
111 }
112 }
113 }
114
115 if ( SUCCEEDED(rc)
116 && !listVM.empty())
117 {
118 ULONG uDelayCurr = 0;
119
120 /* Sort by startup delay and apply base override. */
121 listVM.sort(autostartVMCmp);
122
123 std::list<AUTOSTARTVM>::iterator it;
124 for (it = listVM.begin(); it != listVM.end(); ++it)
125 {
126 ComPtr<IMachine> machine;
127 ComPtr<IProgress> progress;
128
129 if ((*it).uStartupDelay > uDelayCurr)
130 {
131 autostartSvcLogVerbose("Delay starting of the next VMs for %d seconds ...\n",
132 (*it).uStartupDelay - uDelayCurr);
133 RTThreadSleep(((*it).uStartupDelay - uDelayCurr) * 1000);
134 uDelayCurr = (*it).uStartupDelay;
135 }
136
137 CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine((*it).strId.raw(),
138 machine.asOutParam()));
139
140 CHECK_ERROR_BREAK(machine, LaunchVMProcess(g_pSession, Bstr("headless").raw(),
141 Bstr("").raw(), progress.asOutParam()));
142 if (SUCCEEDED(rc) && !progress.isNull())
143 {
144 autostartSvcLogVerbose("Waiting for VM \"%ls\" to power on...\n", (*it).strId.raw());
145 CHECK_ERROR(progress, WaitForCompletion(-1));
146 if (SUCCEEDED(rc))
147 {
148 BOOL completed = true;
149 CHECK_ERROR(progress, COMGETTER(Completed)(&completed));
150 if (SUCCEEDED(rc))
151 {
152 ASSERT(completed);
153
154 LONG iRc;
155 CHECK_ERROR(progress, COMGETTER(ResultCode)(&iRc));
156 if (SUCCEEDED(rc))
157 {
158 if (FAILED(iRc))
159 {
160 ProgressErrorInfo info(progress);
161 com::GluePrintErrorInfo(info);
162 }
163 else
164 autostartSvcLogVerbose("VM \"%ls\" has been successfully started.\n", (*it).strId.raw());
165 }
166 }
167 }
168 }
169 g_pSession->UnlockMachine();
170 }
171 }
172 }
173
174 return rcExit;
175}
176
Note: See TracBrowser for help on using the repository browser.

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