VirtualBox

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

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

OVF: create new IAppliance::read() method instead of reading in constructor; IVirtualBox::openAppliance -> createAppliance; IAppliance->importAppliance -> importMachines

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.8 KB
Line 
1/* $Id: VBoxManageImport.cpp 16668 2009-02-11 14:12:11Z 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 = 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, CreateAppliance(appliance.asOutParam()));
158
159 CHECK_ERROR_BREAK(appliance, Read(bstrOvfFilename));
160
161 RTPrintf("Interpreting %s... ", strOvfFilename.c_str());
162 CHECK_ERROR_BREAK(appliance, Interpret());
163 RTPrintf("OK.\n");
164
165 // fetch all disks
166 com::SafeArray<BSTR> retDisks;
167 CHECK_ERROR_BREAK(appliance,
168 COMGETTER(Disks)(ComSafeArrayAsOutParam(retDisks)));
169 if (retDisks.size() > 0)
170 {
171 RTPrintf("Disks:");
172 for (unsigned i = 0; i < retDisks.size(); i++)
173 RTPrintf(" %ls", retDisks[i]);
174 RTPrintf("\n");
175 }
176
177 // fetch virtual system descriptions
178 com::SafeIfaceArray<IVirtualSystemDescription> aVirtualSystemDescriptions;
179 CHECK_ERROR_BREAK(appliance,
180 COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(aVirtualSystemDescriptions)));
181
182 uint32_t cVirtualSystemDescriptions = aVirtualSystemDescriptions.size();
183
184 // match command line arguments with virtual system descriptions;
185 // this is only to sort out invalid indices at this time
186 ArgsMapsMap::const_iterator it;
187 for (it = mapArgsMapsPerVsys.begin();
188 it != mapArgsMapsPerVsys.end();
189 ++it)
190 {
191 uint32_t ulVsys = it->first;
192 if (ulVsys >= cVirtualSystemDescriptions)
193 return errorSyntax(USAGE_IMPORTAPPLIANCE,
194 "Invalid index %RI32 with -vsys option; the OVF contains only %RI32 virtual system(s).",
195 ulVsys, cVirtualSystemDescriptions);
196 }
197
198 // dump virtual system descriptions and match command-line arguments
199 if (cVirtualSystemDescriptions > 0)
200 {
201 for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
202 {
203 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
204 com::SafeArray<BSTR> aRefs;
205 com::SafeArray<BSTR> aOrigValues;
206 com::SafeArray<BSTR> aConfigValues;
207 com::SafeArray<BSTR> aExtraConfigValues;
208 CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i],
209 GetDescription(ComSafeArrayAsOutParam(retTypes),
210 ComSafeArrayAsOutParam(aRefs),
211 ComSafeArrayAsOutParam(aOrigValues),
212 ComSafeArrayAsOutParam(aConfigValues),
213 ComSafeArrayAsOutParam(aExtraConfigValues)));
214
215 RTPrintf("Virtual system %i:\n", i);
216
217 // look up the corresponding command line options, if any
218 ArgsMap *pmapArgs = NULL;
219 ArgsMapsMap::iterator itm = mapArgsMapsPerVsys.find(i);
220 if (itm != mapArgsMapsPerVsys.end())
221 pmapArgs = &itm->second;
222
223 // this collects the final values for setFinalValues()
224 com::SafeArray<BOOL> aEnabled(retTypes.size());
225 com::SafeArray<BSTR> aFinalValues(retTypes.size());
226
227 for (unsigned a = 0; a < retTypes.size(); ++a)
228 {
229 VirtualSystemDescriptionType_T t = retTypes[a];
230
231 Utf8Str strOverride;
232
233 Bstr bstrFinalValue = aConfigValues[a];
234
235 bool fIgnoreThis = mapIgnoresMapsPerVsys[i][a];
236
237 switch (t)
238 {
239 case VirtualSystemDescriptionType_Name:
240 if (findArgValue(strOverride, pmapArgs, "-vmname"))
241 {
242 bstrFinalValue = strOverride;
243 RTPrintf("%2d: VM name specified with -vmname: \"%ls\"\n",
244 a, bstrFinalValue.raw());
245 }
246 else
247 RTPrintf("%2d: Suggested VM name \"%ls\""
248 "\n (change with \"-vsys %d -vmname <name>\")\n",
249 a, bstrFinalValue.raw(), i);
250 break;
251
252 case VirtualSystemDescriptionType_OS:
253 if (findArgValue(strOverride, pmapArgs, "-ostype"))
254 {
255 bstrFinalValue = strOverride;
256 RTPrintf("%2d: OS type specified with -ostype: \"%ls\"\n",
257 a, bstrFinalValue.raw());
258 }
259 else
260 RTPrintf("%2d: Suggested OS type: \"%ls\""
261 "\n (change with \"-vsys %d -ostype <type>\"; use \"list ostypes\" to list all)\n",
262 a, bstrFinalValue.raw(), i);
263 break;
264
265 case VirtualSystemDescriptionType_CPU:
266 RTPrintf("%2d: Number of CPUs (ignored): %ls\n",
267 a, aConfigValues[a]);
268 break;
269
270 case VirtualSystemDescriptionType_Memory:
271 {
272 if (findArgValue(strOverride, pmapArgs, "-memory"))
273 {
274 uint32_t ulMemMB;
275 if (VINF_SUCCESS == strOverride.toInt(ulMemMB))
276 {
277 bstrFinalValue = strOverride;
278 RTPrintf("%2d: Guest memory specified with -memory: %ls MB\n",
279 a, bstrFinalValue.raw());
280 }
281 else
282 return errorSyntax(USAGE_IMPORTAPPLIANCE,
283 "Argument to -memory option must be a non-negative number.");
284 }
285 else
286 RTPrintf("%2d: Guest memory: %ls MB\n (change with \"-vsys %d -memory <MB>\")\n",
287 a, bstrFinalValue.raw(), i);
288 }
289 break;
290
291 case VirtualSystemDescriptionType_HardDiskControllerIDE:
292 if (fIgnoreThis)
293 {
294 RTPrintf("%2d: IDE controller, type %ls -- disabled\n",
295 a,
296 aConfigValues[a]);
297 aEnabled[a] = false;
298 }
299 else
300 RTPrintf("%2d: IDE controller, type %ls"
301 "\n (disable with \"-vsys %d -ignore %d\")\n",
302 a,
303 aConfigValues[a],
304 i, a);
305 break;
306
307 case VirtualSystemDescriptionType_HardDiskControllerSATA:
308 if (fIgnoreThis)
309 {
310 RTPrintf("%2d: SATA controller, type %ls -- disabled\n",
311 a,
312 aConfigValues[a]);
313 aEnabled[a] = false;
314 }
315 else
316 RTPrintf("%2d: SATA controller, type %ls"
317 "\n (disable with \"-vsys %d -ignore %d\")\n",
318 a,
319 aConfigValues[a],
320 i, a);
321 break;
322
323 case VirtualSystemDescriptionType_HardDiskControllerSCSI:
324 if (fIgnoreThis)
325 {
326 RTPrintf("%2d: SCSI controller, type %ls -- disabled\n",
327 a,
328 aConfigValues[a]);
329 aEnabled[a] = false;
330 }
331 else
332 RTPrintf("%2d: SCSI controller, type %ls"
333 "\n (change with \"-vsys %d -type%d={BusLogic|LsiLogic}\";" // @todo
334 "\n disable with \"-vsys %d -ignore %d\")\n",
335 a,
336 aConfigValues[a],
337 i, a, i, a);
338 break;
339
340 case VirtualSystemDescriptionType_HardDiskImage:
341 if (fIgnoreThis)
342 {
343 RTPrintf("%2d: Hard disk image: source image=%ls -- disabled\n",
344 a,
345 aOrigValues[a]);
346 aEnabled[a] = false;
347 }
348 else
349 RTPrintf("%2d: Hard disk image: source image=%ls, target path=%ls, %ls"
350 "\n (change controller with \"-vsys %d -controller%d=<id>\";" // @todo
351 "\n disable with \"-vsys %d -ignore %d\")\n",
352 a,
353 aOrigValues[a],
354 aConfigValues[a],
355 aExtraConfigValues[a],
356 i, a, i, a);
357 break;
358
359 case VirtualSystemDescriptionType_CDROM:
360 if (fIgnoreThis)
361 {
362 RTPrintf("%2d: CD-ROM -- disabled\n",
363 a);
364 aEnabled[a] = false;
365 }
366 else
367 RTPrintf("%2d: CD-ROM"
368 "\n (disable with \"-vsys %d -ignore %d\")\n",
369 a, i, a);
370 break;
371
372 case VirtualSystemDescriptionType_Floppy:
373 if (fIgnoreThis)
374 {
375 RTPrintf("%2d: Floppy -- disabled\n",
376 a);
377 aEnabled[a] = false;
378 }
379 else
380 RTPrintf("%2d: Floppy"
381 "\n (disable with \"-vsys %d -ignore %d\")\n",
382 a, i, a);
383 break;
384
385 case VirtualSystemDescriptionType_NetworkAdapter:
386 RTPrintf("%2d: Network adapter: orig %ls, config %ls, extra %ls\n", // @todo
387 a,
388 aOrigValues[a],
389 aConfigValues[a],
390 aExtraConfigValues[a]);
391 break;
392
393 case VirtualSystemDescriptionType_USBController:
394 if (fIgnoreThis)
395 {
396 RTPrintf("%2d: USB controller -- disabled\n",
397 a);
398 aEnabled[a] = false;
399 }
400 else
401 RTPrintf("%2d: USB controller"
402 "\n (disable with \"-vsys %d -ignore %d\")\n",
403 a, i, a);
404 break;
405
406 case VirtualSystemDescriptionType_SoundCard:
407 if (fIgnoreThis)
408 {
409 RTPrintf("%2d: Sound card \"%ls\" -- disabled\n",
410 a,
411 aOrigValues[a]);
412 aEnabled[a] = false;
413 }
414 else
415 RTPrintf("%2d: Sound card (appliance expects \"%ls\", can change on import)"
416 "\n (disable with \"-vsys %d -ignore %d\")\n",
417 a,
418 aOrigValues[a],
419 i,
420 a);
421 break;
422 }
423
424 bstrFinalValue.detachTo(&aFinalValues[a]);
425 }
426
427 if (fExecute)
428 CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i],
429 SetFinalValues(ComSafeArrayAsInParam(aEnabled),
430 ComSafeArrayAsInParam(aFinalValues),
431 ComSafeArrayAsInParam(aExtraConfigValues)));
432
433 } // for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
434
435 if (fExecute)
436 {
437 ComPtr<IProgress> progress;
438 CHECK_ERROR_BREAK(appliance,
439 ImportMachines(progress.asOutParam()));
440
441 showProgress(progress);
442
443 if (SUCCEEDED(rc))
444 progress->COMGETTER(ResultCode)(&rc);
445
446 if (FAILED(rc))
447 {
448 com::ProgressErrorInfo info(progress);
449 com::GluePrintErrorInfo(info);
450 com::GluePrintErrorContext("ImportAppliance", __FILE__, __LINE__);
451 }
452 else
453 RTPrintf("Successfully imported the appliance.\n");
454 }
455 } // end if (aVirtualSystemDescriptions.size() > 0)
456 } while (0);
457
458 return SUCCEEDED(rc) ? 0 : 1;
459}
460
461#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