VirtualBox

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

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

VBoxManage: implement remaining options for import

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