VBoxManageImport.cpp revision b8ae33177906f4130b85b7c861cae0e78ed4859b
/* $Id$ */
/** @file
* VBoxManage - The appliance-related commands.
*/
/*
* Copyright (C) 2009 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#ifndef VBOX_ONLY_DOCS
/*******************************************************************************
* Header Files *
*******************************************************************************/
#ifndef VBOX_ONLY_DOCS
#include <list>
#include <map>
#endif /* !VBOX_ONLY_DOCS */
#include "VBoxManage.h"
using namespace com;
// funcs
///////////////////////////////////////////////////////////////////////////////
typedef std::map<uint32_t, ArgsMap> ArgsMapsMap; // map of maps, one for each virtual system, sorted by index
typedef std::map<uint32_t, IgnoresMap> IgnoresMapsMap; // map of maps, one for each virtual system, sorted by index
{
if (pmapArgs)
{
{
return true;
}
}
return false;
}
static const RTGETOPTDEF g_aImportApplianceOptions[] =
{
};
int handleImportAppliance(HandlerArg *a)
{
bool fExecute = true; // if true, then we actually do the import
// for each --vsys X command, maintain a map of command line items
// (we'll parse them later after interpreting the OVF, when we can
// actually check whether they make sense semantically)
int c;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aImportApplianceOptions, RT_ELEMENTS(g_aImportApplianceOptions), 0, 0 /* fFlags */);
{
switch (c)
{
case 'n': // --dry-run
fExecute = false;
break;
case 'P': // --detailed-progress
g_fDetailedProgress = true;
break;
case 's': // --vsys
break;
case 'o': // --ostype
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'V': // --vmname
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'd': // --description
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'L': // --eula
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'm': // --memory
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'u': // --unit
break;
case 'x': // --ignore
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --unit argument.", GetState.pDef->pszLong);
break;
case 'T': // --scsitype
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --unit argument.", GetState.pDef->pszLong);
break;
case 'C': // --controller
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --unit argument.", GetState.pDef->pszLong);
break;
case VINF_GETOPT_NOT_OPTION:
if (strOvfFilename.isEmpty())
else
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
}
if (strOvfFilename.isEmpty())
do
{
char *pszAbsFilePath;
else
{
return 1;
}
// call interpret(); this can yield both warnings and errors, so we need
// to tinker with the error info a bit
{
for (unsigned i = 0; i < cWarnings; ++i)
{
}
}
{
break;
}
RTPrintf("OK.\n");
// fetch all disks
{
RTPrintf("Disks:");
RTPrintf("\n");
}
// fetch virtual system descriptions
// match command line arguments with virtual system descriptions;
// this is only to sort out invalid indices at this time
++it)
{
if (ulVsys >= cVirtualSystemDescriptions)
return errorSyntax(USAGE_IMPORTAPPLIANCE,
"Invalid index %RI32 with -vsys option; the OVF contains only %zu virtual system(s).",
}
// dump virtual system descriptions and match command-line arguments
if (cVirtualSystemDescriptions > 0)
{
for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
{
RTPrintf("Virtual system %u:\n", i);
// look up the corresponding command line options, if any
// this collects the final values for setFinalValues()
{
bool fIgnoreThis = mapIgnoresMapsPerVsys[i][a];
aEnabled[a] = true;
switch (t)
{
{
RTPrintf("%2u: OS type specified with --ostype: \"%ls\"\n",
a, bstrFinalValue.raw());
}
else
RTPrintf("%2u: Suggested OS type: \"%ls\""
"\n (change with \"--vsys %u --ostype <type>\"; use \"list ostypes\" to list all possible values)\n",
a, bstrFinalValue.raw(), i);
break;
{
RTPrintf("%2u: VM name specified with --vmname: \"%ls\"\n",
a, bstrFinalValue.raw());
}
else
RTPrintf("%2u: Suggested VM name \"%ls\""
"\n (change with \"--vsys %u --vmname <name>\")\n",
a, bstrFinalValue.raw(), i);
break;
RTPrintf("%2u: Product (ignored): %ls\n",
a, aVboxValues[a]);
break;
RTPrintf("%2u: ProductUrl (ignored): %ls\n",
a, aVboxValues[a]);
break;
RTPrintf("%2u: Vendor (ignored): %ls\n",
a, aVboxValues[a]);
break;
RTPrintf("%2u: VendorUrl (ignored): %ls\n",
a, aVboxValues[a]);
break;
RTPrintf("%2u: Version (ignored): %ls\n",
a, aVboxValues[a]);
break;
{
RTPrintf("%2u: Description specified with --description: \"%ls\"\n",
a, bstrFinalValue.raw());
}
else
RTPrintf("%2u: Description \"%ls\""
"\n (change with \"--vsys %u --description <desc>\")\n",
a, bstrFinalValue.raw(), i);
break;
{
if (strOverride == "show")
{
RTPrintf("%2u: End-user license agreement"
"\n (accept with \"--vsys %u --eula accept\"):"
"\n\n%ls\n\n",
a, i, bstrFinalValue.raw());
}
else if (strOverride == "accept")
{
RTPrintf("%2u: End-user license agreement (accepted)\n",
a);
}
else
return errorSyntax(USAGE_IMPORTAPPLIANCE,
"Argument to --eula must be either \"show\" or \"accept\".");
}
else
RTPrintf("%2u: End-user license agreement"
"\n (display with \"--vsys %u --eula show\";"
"\n accept with \"--vsys %u --eula accept\")\n",
a, i, i);
break;
RTPrintf("%2u: Number of CPUs (ignored): %ls\n",
a, aVboxValues[a]);
break;
{
{
{
RTPrintf("%2u: Guest memory specified with --memory: %ls MB\n",
a, bstrFinalValue.raw());
}
else
return errorSyntax(USAGE_IMPORTAPPLIANCE,
"Argument to --memory option must be a non-negative number.");
}
else
RTPrintf("%2u: Guest memory: %ls MB\n (change with \"--vsys %u --memory <MB>\")\n",
a, bstrFinalValue.raw(), i);
}
break;
if (fIgnoreThis)
{
RTPrintf("%2u: IDE controller, type %ls -- disabled\n",
a,
aVboxValues[a]);
aEnabled[a] = false;
}
else
RTPrintf("%2u: IDE controller, type %ls"
"\n (disable with \"--vsys %u --unit %u --ignore\")\n",
a,
aVboxValues[a],
i, a);
break;
if (fIgnoreThis)
{
RTPrintf("%2u: SATA controller, type %ls -- disabled\n",
a,
aVboxValues[a]);
aEnabled[a] = false;
}
else
RTPrintf("%2u: SATA controller, type %ls"
"\n (disable with \"--vsys %u --unit %u --ignore\")\n",
a,
aVboxValues[a],
i, a);
break;
if (fIgnoreThis)
{
RTPrintf("%2u: SCSI controller, type %ls -- disabled\n",
a,
aVboxValues[a]);
aEnabled[a] = false;
}
else
{
{
RTPrintf("%2u: SCSI controller, type set with --unit %u --scsitype: \"%ls\"\n",
a,
a,
bstrFinalValue.raw());
}
else
RTPrintf("%2u: SCSI controller, type %ls"
"\n (change with \"--vsys %u --unit %u --scsitype {BusLogic|LsiLogic}\";"
"\n disable with \"--vsys %u --unit %u --ignore\")\n",
a,
aVboxValues[a],
i, a, i, a);
}
break;
if (fIgnoreThis)
{
RTPrintf("%2u: Hard disk image: source image=%ls -- disabled\n",
a,
aOvfValues[a]);
aEnabled[a] = false;
}
else
{
{
// strOverride now has the controller index as a number, but we
// need a "controller=X" format string
RTPrintf("%2u: Hard disk image: source image=%ls, target path=%ls, %ls\n",
a,
aOvfValues[a],
aVboxValues[a],
aExtraConfigValues[a]);
}
else
RTPrintf("%2u: Hard disk image: source image=%ls, target path=%ls, %ls"
"\n (change controller with \"--vsys %u --unit %u --controller <id>\";"
"\n disable with \"--vsys %u --unit %u --ignore\")\n",
a,
aOvfValues[a],
aVboxValues[a],
i, a, i, a);
}
break;
if (fIgnoreThis)
{
RTPrintf("%2u: CD-ROM -- disabled\n",
a);
aEnabled[a] = false;
}
else
RTPrintf("%2u: CD-ROM"
"\n (disable with \"--vsys %u --unit %u --ignore\")\n",
a, i, a);
break;
if (fIgnoreThis)
{
RTPrintf("%2u: Floppy -- disabled\n",
a);
aEnabled[a] = false;
}
else
RTPrintf("%2u: Floppy"
"\n (disable with \"--vsys %u --unit %u --ignore\")\n",
a, i, a);
break;
RTPrintf("%2u: Network adapter: orig %ls, config %ls, extra %ls\n", // @todo implement once we have a plan for the back-end
a,
aOvfValues[a],
aVboxValues[a],
aExtraConfigValues[a]);
break;
if (fIgnoreThis)
{
RTPrintf("%2u: USB controller -- disabled\n",
a);
aEnabled[a] = false;
}
else
RTPrintf("%2u: USB controller"
"\n (disable with \"--vsys %u --unit %u --ignore\")\n",
a, i, a);
break;
if (fIgnoreThis)
{
RTPrintf("%2u: Sound card \"%ls\" -- disabled\n",
a,
aOvfValues[a]);
aEnabled[a] = false;
}
else
RTPrintf("%2u: Sound card (appliance expects \"%ls\", can change on import)"
"\n (disable with \"--vsys %u --unit %u --ignore\")\n",
a,
aOvfValues[a],
i,
a);
break;
}
}
if (fExecute)
} // for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i)
if (cLicensesInTheWay == 1)
RTPrintf("ERROR: Cannot import until the license agreement listed above is accepted.\n");
else if (cLicensesInTheWay > 1)
RTPrintf("ERROR: Cannot import until the %c license agreements listed above are accepted.\n", cLicensesInTheWay);
if (!cLicensesInTheWay && fExecute)
{
// go!
{
return 1;
}
else
RTPrintf("Successfully imported the appliance.\n");
}
} // end if (aVirtualSystemDescriptions.size() > 0)
} while (0);
}
static const RTGETOPTDEF g_aExportOptions[]
= {
};
int handleExportAppliance(HandlerArg *a)
{
// for each --vsys X command, maintain a map of command line items
do
{
int c;
// start at 0 because main() has hacked both the argc and argv given to us
{
switch (c)
{
case 'o': // --output
if (strOutputFile.length())
else
break;
case 'l': // --legacy09
strOvfFormat = "ovf-0.9";
break;
case 's': // --vsys
break;
case 'p': // --product
return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'P': // --producturl
return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'd': // --vendor
return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'D': // --vendorurl
return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'v': // --version
return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'e': // --eula
return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case 'E': // --eulafile
return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
break;
case VINF_GETOPT_NOT_OPTION:
{
// must be machine: try UUID or name
/* assume it's a UUID */
{
/* must be a name */
}
if (machine)
}
break;
default:
if (c > 0)
{
if (RT_C_IS_GRAPH(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
break;
}
break;
if (llMachines.size() == 0)
return errorSyntax(USAGE_EXPORTAPPLIANCE, "At least one machine must be specified with the export command.");
if (!strOutputFile.length())
// match command line arguments with the machines count
// this is only to sort out invalid indices at this time
++it)
{
return errorSyntax(USAGE_EXPORTAPPLIANCE,
"Invalid index %RI32 with -vsys option; you specified only %zu virtual system(s).",
}
uint32_t i=0;
++itM, ++i)
{
// Add additional info to the virtal system description if the user wants so
if (pmapArgs)
{
++itD)
{
pVSD->AddDescription (VirtualSystemDescriptionType_ProductUrl, Bstr(itD->second), Bstr(itD->second));
pVSD->AddDescription (VirtualSystemDescriptionType_VendorUrl, Bstr(itD->second), Bstr(itD->second));
{
void *pvFile;
if (RT_SUCCESS(rc))
{
}
else
{
RTPrintf("ERROR: Cannot read license file \"%s\" which should be included in the virtual system %u.\n",
i);
return 1;
}
}
}
}
}
break;
char *pszAbsFilePath;
else
CHECK_ERROR_BREAK(pAppliance, Write(Bstr(strOvfFormat), Bstr(pszAbsFilePath), progress.asOutParam()));
{
return 1;
}
else
} while (0);
}
#endif /* !VBOX_ONLY_DOCS */