VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageImport.cpp@ 16601

Last change on this file since 16601 was 16601, checked in by vboxsync, 16 years ago

OVF: change IVirtualSystemDescription::setFinalValues method; remove IVirtualSystemDescription::disableItem; API docs; implement lots of VBoxManage import command line handling

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.3 KB
Line 
1/* $Id: VBoxManageImport.cpp 16601 2009-02-09 16:33:28Z vboxsync $ */
2/** @file
3 * VBoxManage - The appliance-related commands.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#ifndef VBOX_ONLY_DOCS
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#ifndef VBOX_ONLY_DOCS
28#include <VBox/com/com.h>
29#include <VBox/com/string.h>
30#include <VBox/com/Guid.h>
31#include <VBox/com/array.h>
32#include <VBox/com/ErrorInfo.h>
33#include <VBox/com/errorprint2.h>
34#include <VBox/com/EventQueue.h>
35
36#include <VBox/com/VirtualBox.h>
37
38#include <list>
39#include <map>
40#endif /* !VBOX_ONLY_DOCS */
41
42#include <iprt/stream.h>
43
44#include <VBox/log.h>
45
46#include "VBoxManage.h"
47using namespace com;
48
49
50// funcs
51///////////////////////////////////////////////////////////////////////////////
52
53typedef std::map<Utf8Str, Utf8Str> ArgsMap; // pairs of strings like "-vmname" => "newvmname"
54typedef std::map<uint32_t, ArgsMap> ArgsMapsMap; // map of maps, one for each virtual system, sorted by index
55
56static bool findArgValue(Utf8Str &strOut,
57 const ArgsMap *pmapArgs,
58 const Utf8Str &strKey)
59{
60 if (pmapArgs)
61 {
62 ArgsMap::const_iterator it;
63 it = pmapArgs->find(strKey);
64 if (it != pmapArgs->end())
65 {
66 strOut = it->second;
67 return true;
68 }
69 }
70
71 return false;
72}
73
74int handleImportAppliance(HandlerArg *a)
75{
76 HRESULT rc = S_OK;
77
78 Utf8Str strOvfFilename;
79 bool fExecute = false; // if true, then we actually do the import (-exec argument)
80
81 uint32_t ulCurVsys = (uint32_t)-1;
82
83 // for each -vsys X command, maintain a map of command line items
84 // (we'll parse them later after interpreting the OVF, when we can
85 // actually check whether they make sense semantically)
86 ArgsMapsMap mapArgsMapsPerVsys;
87
88 for (int i = 0;
89 i < a->argc;
90 ++i)
91 {
92 Utf8Str strThisArg(a->argv[i]);
93 if (strThisArg == "-exec")
94 fExecute = true;
95 else if (strThisArg == "-vsys")
96 {
97 if (++i < a->argc)
98 {
99 uint32_t ulVsys;
100 if (VINF_SUCCESS == (rc = Utf8Str(a->argv[i]).toInt(ulVsys))) // don't use SUCCESS() macro, fail even on warnings
101 ulCurVsys = ulVsys;
102 else
103 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Argument to -vsys option must be a non-negative number.");
104 }
105 else
106 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Missing argument to -vsys option.");
107 }
108 else if ( (strThisArg == "-ostype")
109 || (strThisArg == "-vmname")
110 || (strThisArg == "-memory")
111 || (strThisArg == "-ignore")
112 || (strThisArg.substr(0, 5) == "-type")
113 || (strThisArg.substr(0, 11) == "-controller")
114 )
115 {
116 if (ulCurVsys == (uint32_t)-1)
117 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding -vsys argument.", strThisArg.c_str());
118
119 // store both this arg and the next one in the strings map for later parsing
120 if (++i < a->argc)
121 mapArgsMapsPerVsys[ulCurVsys][strThisArg] = Utf8Str(a->argv[i]);
122 else
123 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Missing argument to \"%s\" option.", strThisArg.c_str());
124 }
125 else if (strThisArg[0] == '-')
126 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Unknown option \"%s\".", strThisArg.c_str());
127 else if (!strOvfFilename)
128 strOvfFilename = strThisArg;
129 else
130 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Too many arguments for \"import\" command.");
131 }
132
133 if (!strOvfFilename)
134 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Not enough arguments for \"import\" command.");
135
136 do
137 {
138 Bstr bstrOvfFilename(strOvfFilename);
139 ComPtr<IAppliance> appliance;
140 CHECK_ERROR_BREAK(a->virtualBox, OpenAppliance(bstrOvfFilename, appliance.asOutParam()));
141
142 RTPrintf("Interpreting %s... ", strOvfFilename.c_str());
143 CHECK_ERROR_BREAK(appliance, Interpret());
144 RTPrintf("OK.\n");
145
146 // fetch all disks
147 com::SafeArray<BSTR> retDisks;
148 CHECK_ERROR_BREAK(appliance,
149 COMGETTER(Disks)(ComSafeArrayAsOutParam(retDisks)));
150 if (retDisks.size() > 0)
151 {
152 RTPrintf("Disks:");
153 for (unsigned i = 0; i < retDisks.size(); i++)
154 RTPrintf(" %ls", retDisks[i]);
155 RTPrintf("\n");
156 }
157
158 // fetch virtual system descriptions
159 com::SafeIfaceArray<IVirtualSystemDescription> aVirtualSystemDescriptions;
160 CHECK_ERROR_BREAK(appliance,
161 COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(aVirtualSystemDescriptions)));
162
163 uint32_t cVirtualSystemDescriptions = aVirtualSystemDescriptions.size();
164
165 // match command line arguments with virtual system descriptions;
166 // this is only to sort out invalid indices at this time
167 ArgsMapsMap::const_iterator it;
168 for (it = mapArgsMapsPerVsys.begin();
169 it != mapArgsMapsPerVsys.end();
170 ++it)
171 {
172 uint32_t ulVsys = it->first;
173 if (ulVsys >= cVirtualSystemDescriptions)
174 return errorSyntax(USAGE_IMPORTAPPLIANCE,
175 "Invalid index %RI32 with -vsys option; the OVF contains only %RI32 virtual system(s).",
176 ulVsys, cVirtualSystemDescriptions);
177 }
178
179 // dump virtual system descriptions and match command-line arguments
180 if (cVirtualSystemDescriptions > 0)
181 {
182 for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
183 {
184 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
185 com::SafeArray<BSTR> aRefs;
186 com::SafeArray<BSTR> aOrigValues;
187 com::SafeArray<BSTR> aConfigValues;
188 com::SafeArray<BSTR> aExtraConfigValues;
189 CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i],
190 GetDescription(ComSafeArrayAsOutParam(retTypes),
191 ComSafeArrayAsOutParam(aRefs),
192 ComSafeArrayAsOutParam(aOrigValues),
193 ComSafeArrayAsOutParam(aConfigValues),
194 ComSafeArrayAsOutParam(aExtraConfigValues)));
195
196 RTPrintf("Virtual system %i:\n", i);
197
198 // look up the corresponding command line options, if any
199 const ArgsMap *pmapArgs = NULL;
200 ArgsMapsMap::const_iterator itm = mapArgsMapsPerVsys.find(i);
201 if (itm != mapArgsMapsPerVsys.end())
202 pmapArgs = &itm->second;
203
204// ArgsMap::const_iterator it3;
205// for (it3 = pmapArgs->begin();
206// it3 != pmapArgs->end();
207// ++it3)
208// {
209// RTPrintf("%s -> %s\n", it3->first.c_str(), it3->second.c_str());
210// }
211// }
212
213// Bstr bstrVMName;
214// Bstr bstrOSType;
215
216 // this collects the final values for setFinalValues()
217 com::SafeArray<BOOL> aEnabled(retTypes.size());
218 com::SafeArray<BSTR> aFinalValues(retTypes.size());
219
220 for (unsigned a = 0; a < retTypes.size(); ++a)
221 {
222 VirtualSystemDescriptionType_T t = retTypes[a];
223
224 Utf8Str strOverride;
225
226 Bstr bstrFinalValue = aConfigValues[a];
227
228 switch (t)
229 {
230 case VirtualSystemDescriptionType_Name:
231 if (findArgValue(strOverride, pmapArgs, "-vmname"))
232 {
233 bstrFinalValue = strOverride;
234 RTPrintf("%2d: VM name specified with -vmname: \"%ls\"\n",
235 a, bstrFinalValue.raw());
236 }
237 else
238 RTPrintf("%2d: Suggested VM name \"%ls\""
239 "\n (change with \"-vsys %d -vmname <name>\")\n",
240 a, bstrFinalValue.raw(), i);
241 break;
242
243 case VirtualSystemDescriptionType_OS:
244 if (findArgValue(strOverride, pmapArgs, "-ostype"))
245 {
246 bstrFinalValue = strOverride;
247 RTPrintf("%2d: OS type specified with -ostype: \"%ls\"\n",
248 a, bstrFinalValue.raw());
249 }
250 else
251 RTPrintf("%2d: Suggested OS type: \"%ls\""
252 "\n (change with \"-vsys %d -ostype <type>\"; use \"list ostypes\" to list all)\n",
253 a, bstrFinalValue.raw(), i);
254 break;
255
256 case VirtualSystemDescriptionType_CPU:
257 RTPrintf("%2d: Number of CPUs (ignored): %ls\n",
258 a, aConfigValues[a]);
259 break;
260
261 case VirtualSystemDescriptionType_Memory:
262 {
263 if (findArgValue(strOverride, pmapArgs, "-memory"))
264 {
265 uint32_t ulMemMB;
266 if (VINF_SUCCESS == strOverride.toInt(ulMemMB))
267 {
268 bstrFinalValue = strOverride;
269 RTPrintf("%2d: Guest memory specified with -memory: %ls MB\n",
270 a, bstrFinalValue.raw());
271 }
272 else
273 return errorSyntax(USAGE_IMPORTAPPLIANCE,
274 "Argument to -memory option must be a non-negative number.");
275 }
276 else
277 RTPrintf("%2d: Guest memory: %ls MB\n (change with \"-vsys %d -memory <MB>\")\n",
278 a, bstrFinalValue.raw(), i);
279 }
280 break;
281
282 case VirtualSystemDescriptionType_HardDiskControllerIDE:
283 RTPrintf("%2d: IDE controller, type %ls"
284 "\n (disable with \"-vsys %d -ignore %d\")\n",
285 a,
286 aConfigValues[a],
287 i, a);
288 break;
289
290 case VirtualSystemDescriptionType_HardDiskControllerSATA:
291 RTPrintf("%2d: SATA controller, type %ls"
292 "\n (disable with \"-vsys %d -ignore %d\")\n",
293 a,
294 aConfigValues[a],
295 i, a);
296 break;
297
298 case VirtualSystemDescriptionType_HardDiskControllerSCSI:
299 RTPrintf("%2d: SCSI controller, type %ls"
300 "\n (change with \"-vsys %d -type%d={BusLogic|LsiLogic}\";"
301 "\n disable with \"-vsys %d -ignore %d\")\n",
302 a,
303 aConfigValues[a],
304 i, a, i, a);
305 break;
306
307 case VirtualSystemDescriptionType_HardDiskImage:
308 RTPrintf("%2d: Hard disk image: source image=%ls, target path=%ls, %ls"
309 "\n (change controller with \"-vsys %d -controller%d=<id>\";"
310 "\n disable with \"-vsys %d -ignore %d\")\n",
311 a,
312 aOrigValues[a],
313 aConfigValues[a],
314 aExtraConfigValues[a],
315 i, a, i, a);
316 break;
317
318 case VirtualSystemDescriptionType_CDROM:
319 RTPrintf("%2d: CD-ROM"
320 "\n (disable with \"-vsys %d -ignore %d\")\n",
321 a, i, a);
322 break;
323
324 case VirtualSystemDescriptionType_Floppy:
325 RTPrintf("%2d: Floppy"
326 "\n (disable with \"-vsys %d -ignore %d\")\n",
327 a, i, a);
328 break;
329
330 case VirtualSystemDescriptionType_NetworkAdapter:
331 RTPrintf("%2d: Network adapter: orig %ls, config %ls, extra %ls\n",
332 a,
333 aOrigValues[a],
334 aConfigValues[a],
335 aExtraConfigValues[a]);
336 break;
337
338 case VirtualSystemDescriptionType_USBController:
339 RTPrintf("%2d: USB controller"
340 "\n (disable with \"-vsys %d -ignore %d\")\n",
341 a, i, a);
342 break;
343
344 case VirtualSystemDescriptionType_SoundCard:
345 RTPrintf("%2d: Sound card (appliance expects \"%ls\", can change on import)"
346 "\n (disable with \"-vsys %d -ignore %d\")\n",
347 a,
348 aOrigValues[a],
349 i,
350 a);
351 break;
352 }
353
354 bstrFinalValue.detachTo(&aFinalValues[a]);
355 }
356
357 if (fExecute)
358 CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i],
359 SetFinalValues(ComSafeArrayAsInParam(aEnabled),
360 ComSafeArrayAsInParam(aFinalValues)));
361
362 } // for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
363
364 if (fExecute)
365 {
366 ComPtr<IProgress> progress;
367 CHECK_ERROR_BREAK(appliance,
368 ImportAppliance(progress.asOutParam()));
369
370 showProgress(progress);
371
372 if (SUCCEEDED(rc))
373 progress->COMGETTER(ResultCode)(&rc);
374
375 if (FAILED(rc))
376 {
377 com::ProgressErrorInfo info(progress);
378 com::GluePrintErrorInfo(info);
379 com::GluePrintErrorContext("ImportAppliance", __FILE__, __LINE__);
380 }
381 else
382 RTPrintf("Successfully imported the appliance.\n");
383 }
384 } // end if (aVirtualSystemDescriptions.size() > 0)
385 } while (0);
386
387 return SUCCEEDED(rc) ? 0 : 1;
388}
389
390#endif /* !VBOX_ONLY_DOCS */
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