VirtualBox

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

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

OVF: add -ignore command to VBoxManage -import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.6 KB
Line 
1/* $Id: VBoxManageImport.cpp 16606 2009-02-09 17:17:34Z 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
56typedef std::map<uint32_t, bool> IgnoresMap; // pairs of numeric description entry indices
57typedef std::map<uint32_t, IgnoresMap> IgnoresMapsMap; // map of maps, one for each virtual system, sorted by index
58
59static bool findArgValue(Utf8Str &strOut,
60 ArgsMap *pmapArgs,
61 const Utf8Str &strKey)
62{
63 if (pmapArgs)
64 {
65 ArgsMap::iterator it;
66 it = pmapArgs->find(strKey);
67 if (it != pmapArgs->end())
68 {
69 strOut = it->second;
70 pmapArgs->erase(it);
71 return true;
72 }
73 }
74
75 return false;
76}
77
78int handleImportAppliance(HandlerArg *a)
79{
80 HRESULT rc = S_OK;
81
82 Utf8Str strOvfFilename;
83 bool fExecute = false; // if true, then we actually do the import (-exec argument)
84
85 uint32_t ulCurVsys = (uint32_t)-1;
86
87 // for each -vsys X command, maintain a map of command line items
88 // (we'll parse them later after interpreting the OVF, when we can
89 // actually check whether they make sense semantically)
90 ArgsMapsMap mapArgsMapsPerVsys;
91 IgnoresMapsMap mapIgnoresMapsPerVsys;
92
93 for (int i = 0;
94 i < a->argc;
95 ++i)
96 {
97 bool fIsIgnore = false;
98 Utf8Str strThisArg(a->argv[i]);
99 if (strThisArg == "-exec")
100 fExecute = true;
101 else if (strThisArg == "-vsys")
102 {
103 if (++i < a->argc)
104 {
105 uint32_t ulVsys;
106 if (VINF_SUCCESS != (rc = Utf8Str(a->argv[i]).toInt(ulVsys))) // don't use SUCCESS() macro, fail even on warnings
107 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Argument to -vsys option must be a non-negative number.");
108
109 ulCurVsys = ulVsys;
110 }
111 else
112 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Missing argument to -vsys option.");
113 }
114 else if ( (strThisArg == "-ostype")
115 || (strThisArg == "-vmname")
116 || (strThisArg == "-memory")
117 || (fIsIgnore = (strThisArg == "-ignore"))
118 || (strThisArg.substr(0, 5) == "-type")
119 || (strThisArg.substr(0, 11) == "-controller")
120 )
121 {
122 if (ulCurVsys == (uint32_t)-1)
123 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding -vsys argument.", strThisArg.c_str());
124
125 if (++i < a->argc)
126 if (fIsIgnore)
127 {
128 uint32_t ulItem;
129 if (VINF_SUCCESS != Utf8Str(a->argv[i]).toInt(ulItem))
130 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Argument to -vsys option must be a non-negative number.");
131
132 mapIgnoresMapsPerVsys[ulCurVsys][ulItem] = true;
133 }
134 else
135 {
136 // store both this arg and the next one in the strings map for later parsing
137 mapArgsMapsPerVsys[ulCurVsys][strThisArg] = Utf8Str(a->argv[i]);
138 }
139 else
140 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Missing argument to \"%s\" option.", strThisArg.c_str());
141 }
142 else if (strThisArg[0] == '-')
143 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Unknown option \"%s\".", strThisArg.c_str());
144 else if (!strOvfFilename)
145 strOvfFilename = strThisArg;
146 else
147 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Too many arguments for \"import\" command.");
148 }
149
150 if (!strOvfFilename)
151 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Not enough arguments for \"import\" command.");
152
153 do
154 {
155 Bstr bstrOvfFilename(strOvfFilename);
156 ComPtr<IAppliance> appliance;
157 CHECK_ERROR_BREAK(a->virtualBox, OpenAppliance(bstrOvfFilename, appliance.asOutParam()));
158
159 RTPrintf("Interpreting %s... ", strOvfFilename.c_str());
160 CHECK_ERROR_BREAK(appliance, Interpret());
161 RTPrintf("OK.\n");
162
163 // fetch all disks
164 com::SafeArray<BSTR> retDisks;
165 CHECK_ERROR_BREAK(appliance,
166 COMGETTER(Disks)(ComSafeArrayAsOutParam(retDisks)));
167 if (retDisks.size() > 0)
168 {
169 RTPrintf("Disks:");
170 for (unsigned i = 0; i < retDisks.size(); i++)
171 RTPrintf(" %ls", retDisks[i]);
172 RTPrintf("\n");
173 }
174
175 // fetch virtual system descriptions
176 com::SafeIfaceArray<IVirtualSystemDescription> aVirtualSystemDescriptions;
177 CHECK_ERROR_BREAK(appliance,
178 COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(aVirtualSystemDescriptions)));
179
180 uint32_t cVirtualSystemDescriptions = aVirtualSystemDescriptions.size();
181
182 // match command line arguments with virtual system descriptions;
183 // this is only to sort out invalid indices at this time
184 ArgsMapsMap::const_iterator it;
185 for (it = mapArgsMapsPerVsys.begin();
186 it != mapArgsMapsPerVsys.end();
187 ++it)
188 {
189 uint32_t ulVsys = it->first;
190 if (ulVsys >= cVirtualSystemDescriptions)
191 return errorSyntax(USAGE_IMPORTAPPLIANCE,
192 "Invalid index %RI32 with -vsys option; the OVF contains only %RI32 virtual system(s).",
193 ulVsys, cVirtualSystemDescriptions);
194 }
195
196 // dump virtual system descriptions and match command-line arguments
197 if (cVirtualSystemDescriptions > 0)
198 {
199 for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
200 {
201 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
202 com::SafeArray<BSTR> aRefs;
203 com::SafeArray<BSTR> aOrigValues;
204 com::SafeArray<BSTR> aConfigValues;
205 com::SafeArray<BSTR> aExtraConfigValues;
206 CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i],
207 GetDescription(ComSafeArrayAsOutParam(retTypes),
208 ComSafeArrayAsOutParam(aRefs),
209 ComSafeArrayAsOutParam(aOrigValues),
210 ComSafeArrayAsOutParam(aConfigValues),
211 ComSafeArrayAsOutParam(aExtraConfigValues)));
212
213 RTPrintf("Virtual system %i:\n", i);
214
215 // look up the corresponding command line options, if any
216 ArgsMap *pmapArgs = NULL;
217 ArgsMapsMap::iterator itm = mapArgsMapsPerVsys.find(i);
218 if (itm != mapArgsMapsPerVsys.end())
219 pmapArgs = &itm->second;
220
221 // this collects the final values for setFinalValues()
222 com::SafeArray<BOOL> aEnabled(retTypes.size());
223 com::SafeArray<BSTR> aFinalValues(retTypes.size());
224
225 for (unsigned a = 0; a < retTypes.size(); ++a)
226 {
227 VirtualSystemDescriptionType_T t = retTypes[a];
228
229 Utf8Str strOverride;
230
231 Bstr bstrFinalValue = aConfigValues[a];
232
233 bool fIgnoreThis = mapIgnoresMapsPerVsys[i][a];
234
235 switch (t)
236 {
237 case VirtualSystemDescriptionType_Name:
238 if (findArgValue(strOverride, pmapArgs, "-vmname"))
239 {
240 bstrFinalValue = strOverride;
241 RTPrintf("%2d: VM name specified with -vmname: \"%ls\"\n",
242 a, bstrFinalValue.raw());
243 }
244 else
245 RTPrintf("%2d: Suggested VM name \"%ls\""
246 "\n (change with \"-vsys %d -vmname <name>\")\n",
247 a, bstrFinalValue.raw(), i);
248 break;
249
250 case VirtualSystemDescriptionType_OS:
251 if (findArgValue(strOverride, pmapArgs, "-ostype"))
252 {
253 bstrFinalValue = strOverride;
254 RTPrintf("%2d: OS type specified with -ostype: \"%ls\"\n",
255 a, bstrFinalValue.raw());
256 }
257 else
258 RTPrintf("%2d: Suggested OS type: \"%ls\""
259 "\n (change with \"-vsys %d -ostype <type>\"; use \"list ostypes\" to list all)\n",
260 a, bstrFinalValue.raw(), i);
261 break;
262
263 case VirtualSystemDescriptionType_CPU:
264 RTPrintf("%2d: Number of CPUs (ignored): %ls\n",
265 a, aConfigValues[a]);
266 break;
267
268 case VirtualSystemDescriptionType_Memory:
269 {
270 if (findArgValue(strOverride, pmapArgs, "-memory"))
271 {
272 uint32_t ulMemMB;
273 if (VINF_SUCCESS == strOverride.toInt(ulMemMB))
274 {
275 bstrFinalValue = strOverride;
276 RTPrintf("%2d: Guest memory specified with -memory: %ls MB\n",
277 a, bstrFinalValue.raw());
278 }
279 else
280 return errorSyntax(USAGE_IMPORTAPPLIANCE,
281 "Argument to -memory option must be a non-negative number.");
282 }
283 else
284 RTPrintf("%2d: Guest memory: %ls MB\n (change with \"-vsys %d -memory <MB>\")\n",
285 a, bstrFinalValue.raw(), i);
286 }
287 break;
288
289 case VirtualSystemDescriptionType_HardDiskControllerIDE:
290 if (fIgnoreThis)
291 {
292 RTPrintf("%2d: IDE controller, type %ls -- disabled\n",
293 a,
294 aConfigValues[a]);
295 aEnabled[a] = false;
296 }
297 else
298 RTPrintf("%2d: IDE controller, type %ls"
299 "\n (disable with \"-vsys %d -ignore %d\")\n",
300 a,
301 aConfigValues[a],
302 i, a);
303 break;
304
305 case VirtualSystemDescriptionType_HardDiskControllerSATA:
306 if (fIgnoreThis)
307 {
308 RTPrintf("%2d: SATA controller, type %ls -- disabled\n",
309 a,
310 aConfigValues[a]);
311 aEnabled[a] = false;
312 }
313 else
314 RTPrintf("%2d: SATA controller, type %ls"
315 "\n (disable with \"-vsys %d -ignore %d\")\n",
316 a,
317 aConfigValues[a],
318 i, a);
319 break;
320
321 case VirtualSystemDescriptionType_HardDiskControllerSCSI:
322 if (fIgnoreThis)
323 {
324 RTPrintf("%2d: SCSI controller, type %ls -- disabled\n",
325 a,
326 aConfigValues[a]);
327 aEnabled[a] = false;
328 }
329 else
330 RTPrintf("%2d: SCSI controller, type %ls"
331 "\n (change with \"-vsys %d -type%d={BusLogic|LsiLogic}\";" // @todo
332 "\n disable with \"-vsys %d -ignore %d\")\n",
333 a,
334 aConfigValues[a],
335 i, a, i, a);
336 break;
337
338 case VirtualSystemDescriptionType_HardDiskImage:
339 if (fIgnoreThis)
340 {
341 RTPrintf("%2d: Hard disk image: source image=%ls -- disabled\n",
342 a,
343 aOrigValues[a]);
344 aEnabled[a] = false;
345 }
346 else
347 RTPrintf("%2d: Hard disk image: source image=%ls, target path=%ls, %ls"
348 "\n (change controller with \"-vsys %d -controller%d=<id>\";" // @todo
349 "\n disable with \"-vsys %d -ignore %d\")\n",
350 a,
351 aOrigValues[a],
352 aConfigValues[a],
353 aExtraConfigValues[a],
354 i, a, i, a);
355 break;
356
357 case VirtualSystemDescriptionType_CDROM:
358 if (fIgnoreThis)
359 {
360 RTPrintf("%2d: CD-ROM -- disabled\n",
361 a);
362 aEnabled[a] = false;
363 }
364 else
365 RTPrintf("%2d: CD-ROM"
366 "\n (disable with \"-vsys %d -ignore %d\")\n",
367 a, i, a);
368 break;
369
370 case VirtualSystemDescriptionType_Floppy:
371 if (fIgnoreThis)
372 {
373 RTPrintf("%2d: Floppy -- disabled\n",
374 a);
375 aEnabled[a] = false;
376 }
377 else
378 RTPrintf("%2d: Floppy"
379 "\n (disable with \"-vsys %d -ignore %d\")\n",
380 a, i, a);
381 break;
382
383 case VirtualSystemDescriptionType_NetworkAdapter:
384 RTPrintf("%2d: Network adapter: orig %ls, config %ls, extra %ls\n", // @todo
385 a,
386 aOrigValues[a],
387 aConfigValues[a],
388 aExtraConfigValues[a]);
389 break;
390
391 case VirtualSystemDescriptionType_USBController:
392 if (fIgnoreThis)
393 {
394 RTPrintf("%2d: USB controller -- disabled\n",
395 a);
396 aEnabled[a] = false;
397 }
398 else
399 RTPrintf("%2d: USB controller"
400 "\n (disable with \"-vsys %d -ignore %d\")\n",
401 a, i, a);
402 break;
403
404 case VirtualSystemDescriptionType_SoundCard:
405 if (fIgnoreThis)
406 {
407 RTPrintf("%2d: Sound card \"%ls\" -- disabled\n",
408 a,
409 aOrigValues[a]);
410 aEnabled[a] = false;
411 }
412 else
413 RTPrintf("%2d: Sound card (appliance expects \"%ls\", can change on import)"
414 "\n (disable with \"-vsys %d -ignore %d\")\n",
415 a,
416 aOrigValues[a],
417 i,
418 a);
419 break;
420 }
421
422 bstrFinalValue.detachTo(&aFinalValues[a]);
423 }
424
425 if (fExecute)
426 CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i],
427 SetFinalValues(ComSafeArrayAsInParam(aEnabled),
428 ComSafeArrayAsInParam(aFinalValues)));
429
430 } // for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
431
432 if (fExecute)
433 {
434 ComPtr<IProgress> progress;
435 CHECK_ERROR_BREAK(appliance,
436 ImportAppliance(progress.asOutParam()));
437
438 showProgress(progress);
439
440 if (SUCCEEDED(rc))
441 progress->COMGETTER(ResultCode)(&rc);
442
443 if (FAILED(rc))
444 {
445 com::ProgressErrorInfo info(progress);
446 com::GluePrintErrorInfo(info);
447 com::GluePrintErrorContext("ImportAppliance", __FILE__, __LINE__);
448 }
449 else
450 RTPrintf("Successfully imported the appliance.\n");
451 }
452 } // end if (aVirtualSystemDescriptions.size() > 0)
453 } while (0);
454
455 return SUCCEEDED(rc) ? 0 : 1;
456}
457
458#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