ApplianceImpl.cpp revision 5ff3fa0492332325f57e80636321619e2224027e
/* $Id$ */
/** @file
*
* IAppliance and IVirtualSystem COM class implementations
*/
/*
* Copyright (C) 2008-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.
*/
#include "ApplianceImpl.h"
#include "VirtualBoxImpl.h"
#include "GuestOSTypeImpl.h"
#include "ProgressImpl.h"
#include "Logging.h"
#include <iostream>
#include <sstream>
using namespace std;
// defines
////////////////////////////////////////////////////////////////////////////////
struct DiskImage
{
// (maximum size for dynamic images, I guess; we always translate this to bytes)
// (actual used size of disk, always in bytes; can be an estimate of used disk
// space, but cannot be larger than iCapacity)
// typically http://www.vmware.com/specifications/vmdk.html#sparse
// fields from /References/File; the spec says the file reference from disk can be empty,
// so in that case, strFilename will be empty, then a new disk should be created
Utf8Str strHref; // value from /References/File/@href (filename); if empty, then the remaining fields are ignored
int64_t iSize; // value from /References/File/@size (optional according to spec; then we set -1 here)
Utf8Str strCompression; // value from /References/File/@compression (optional, can be "gzip" according to spec)
};
struct Network
{
// unfortunately the OVF spec is unspecific about how networks should be specified further
};
struct VirtualHardwareItem
{
Utf8Str strHostResource; // "Abstractly specifies how a device shall connect to a resource on the deployment platform.
// Not all devices need a backing." Used with disk items, for which this references a virtual
// disk from the Disks section.
bool fAutomaticAllocation;
bool fAutomaticDeallocation;
Utf8Str strConnection; // "All Ethernet adapters that specify the same abstract network connection name within an OVF
// package shall be deployed on the same network. The abstract network connection name shall be
// listed in the NetworkSection at the outermost envelope level."
Utf8Str strAllocationUnits; // "Specifies the units of allocation used. For example, “byte * 2^20”."
uint64_t ullVirtualQuantity; // "Specifies the quantity of resources presented. For example, “256”."
uint64_t ullReservation; // "Specifies the minimum quantity of resources guaranteed to be available."
uint64_t ullWeight; // "Specifies a relative priority for this allocation in relation to other allocations."
: ulInstanceID(0), fAutomaticAllocation(false), fAutomaticDeallocation(false), ullVirtualQuantity(0), ullReservation(0), ullLimit(0), ullWeight(0), ulBusNumber(0), ulLineNumber(0)
{};
};
struct VirtualSystem;
// opaque private instance data of Appliance class
{
};
struct HardDiskController
{
Utf8Str strControllerType; // controller subtype (Item/ResourceSubType); e.g. "LsiLogic"; can be empty (esp. for IDE)
: idController(0),
ulBusNumber(0)
{
}
};
struct VirtualDisk
{
// points into VirtualSystem.mapControllers
// this receives the <id> component; points to one of the
// references in Appliance::Data.mapDisks
};
struct VirtualSystem
{
Utf8Str strVirtualSystemType; // generic hardware description; OVF says this can be something like "vmx-4" or "xen";
// VMware Workstation 6.5 is "vmx-07"
// list of strings referring to network names
// (one for each VirtualSystem/Item[@ResourceType=10]/Connection element)
// list of hard disk controllers
// (one for each VirtualSystem/Item[@ResourceType=6] element with accumulated data from children)
// (one for each VirtualSystem/Item[@ResourceType=17] element with accumulated data from children)
bool fHasFloppyDrive; // true if there's a floppy item in mapHardwareItems
bool fHasCdromDrive; // true if there's a CD-ROM item in mapHardwareItems; ISO images are not yet supported by OVFtool
bool fHasUsbController; // true if there's a USB controller item in mapHardwareItems
Utf8Str strSoundCardType; // if not empty, then the system wants a soundcard; this then specifies the hardware;
// VMware Workstation 6.5 uses "ensoniq1371" for example
Utf8Str strLicenceText; // license info if any; receives contents of VirtualSystem/EulaSection/License
: ullMemorySize(0), cCPUs(1), fHasFloppyDrive(false), fHasCdromDrive(false), fHasUsbController(false)
{
}
};
{
{}
~Task() {}
};
// globals
////////////////////////////////////////////////////////////////////////////////
template <class T>
inline
{
// @todo optimize
}
{
return str2;
}
// IVirtualBox public methods
////////////////////////////////////////////////////////////////////////////////
/**
* Implementation for IVirtualBox::openAppliance. Loads the given appliance (see API reference).
*
* @param bstrPath Appliance to open (either .ovf or .ova file, see API reference)
* @param anAppliance IAppliance object created if S_OK is returned.
* @return S_OK or error.
*/
{
// ComAssertComRCThrowRC(rc);
return rc;
}
// Appliance::task methods
////////////////////////////////////////////////////////////////////////////////
{
"Appliance::Task");
return S_OK;
}
// IAppliance constructor / destructor
////////////////////////////////////////////////////////////////////////////////
struct shutup {};
// IAppliance private methods
////////////////////////////////////////////////////////////////////////////////
/**
* Private helper method that goes thru the elements of the given "current" element in the OVF XML
* and handles the contained child elements (which can be "Section" or "Content" elements).
*
* @param pcszPath Path spec of the XML file, for error messages.
* @param pReferencesElement "References" element from OVF, for looking up file specifications; can be NULL if no such element is present.
* @param pCurElem Element whose children are to be analyzed here.
* @return
*/
{
{
const char *pcszTypeAttr = "";
)
)
{
return rc;
}
)
)
{
return rc;
}
{
// TODO
}
{
// child of VirtualSystemCollection -- TODO
}
{
// child of VirtualSystemCollection -- TODO
}
{
// child of VirtualSystemCollection -- TODO
}
)
)
{
return rc;
}
)
)
{
// TODO ResourceAllocationSection
// recurse for this, since it has VirtualSystem elements as children
return rc;
}
}
return S_OK;
}
/**
* Private helper method that handles disk sections in the OVF XML.
* @param pcszPath Path spec of the XML file, for error messages.
* @param pReferencesElement "References" element from OVF, for looking up file specifications; can be NULL if no such element is present.
* @param pSectionElem Section element for which this helper is getting called.
* @return
*/
{
// contains "Disk" child elements
{
DiskImage d;
pcszBad = "diskId";
pcszBad = "format";
pcszBad = "capacity";
else
{
// optional
d.iPopulatedSize = -1;
{
// look up corresponding /References/File nodes (list built above)
if ( pReferencesElem
)
{
// copy remaining values from file node then
const char *pcszBadInFile = NULL;
pcszBadInFile = "href";
// if (!(pFileElem->getAttributeValue("size", d.iChunkSize))) TODO
if (pcszBadInFile)
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": missing or invalid attribute '%s' in 'File' element, line %d"),
pFileElem->getLineNumber());
}
else
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": cannot find References/File element for ID '%s' referenced by 'Disk' element, line %d"),
strFileRef.c_str(),
pelmDisk->getLineNumber());
}
}
if (pcszBad)
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": missing or invalid attribute '%s' in 'DiskSection' element, line %d"),
pelmDisk->getLineNumber());
}
return S_OK;
}
/**
* Private helper method that handles network sections in the OVF XML.
* @param pcszPath Path spec of the XML file, for error messages.
* @param pSectionElem Section element for which this helper is getting called.
* @return
*/
{
// contains "Disk" child elements
{
Network n;
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": missing 'name' attribute in 'Network', line %d"),
pelmNetwork->getLineNumber());
m->mapNetworks[n.strNetworkName] = n;
}
return S_OK;
}
/**
* Private helper method that handles a "VirtualSystem" element in the OVF XML.
*
* @param pcszPath
* @param pContentElem
* @return
*/
{
if (pIdAttr)
{
{
/* <EulaSection>
<Info ovf:msgid="6">License agreement for the Virtual System.</Info>
<License ovf:msgid="1">License terms can go in here.</License>
</EulaSection> */
)
{
}
}
)
{
{
/* <System>
<vssd:Description>Description of the virtual hardware section.</vssd:Description>
<vssd:ElementName>vmware</vssd:ElementName>
<vssd:InstanceID>1</vssd:InstanceID>
<vssd:VirtualSystemIdentifier>MyLampService</vssd:VirtualSystemIdentifier>
<vssd:VirtualSystemType>vmx-4</vssd:VirtualSystemType>
</System>*/
}
{
{
)
{
}
else
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": unknown element \"%s\" under Item element, line %d"),
i.ulLineNumber);
}
// store!
}
++itH)
{
// do some analysis
switch (i.resourceType)
{
case OVFResourceType_Processor: // 3
/* <rasd:Caption>1 virtual CPU</rasd:Caption>
<rasd:Description>Number of virtual CPUs</rasd:Description>
<rasd:ElementName>virtual CPU</rasd:ElementName>
<rasd:InstanceID>1</rasd:InstanceID>
<rasd:ResourceType>3</rasd:ResourceType>
<rasd:VirtualQuantity>1</rasd:VirtualQuantity>*/
if (i.ullVirtualQuantity < UINT16_MAX)
else
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": CPU count %RI64 is larger than %d, line %d"),
i.ulLineNumber);
break;
case OVFResourceType_Memory: // 4
)
else
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": Invalid allocation unit \"%s\" specified with memory size item, line %d"),
i.strAllocationUnits.c_str(),
i.ulLineNumber);
break;
case OVFResourceType_IdeController: // 5 IdeController
{
/* <Item>
<rasd:Caption>ideController0</rasd:Caption>
<rasd:Description>IDE Controller</rasd:Description>
<rasd:InstanceId>5</rasd:InstanceId>
<rasd:ResourceType>5</rasd:ResourceType>
<rasd:Address>0</rasd:Address>
<rasd:BusNumber>0</rasd:BusNumber>
</Item> */
}
break;
case OVFResourceType_ParallelScsiHba: // 6 SCSI controller
{
/* <Item>
<rasd:Caption>SCSI Controller 0 - LSI Logic</rasd:Caption>
<rasd:Description>SCI Controller</rasd:Description>
<rasd:ElementName>SCSI controller</rasd:ElementName>
<rasd:InstanceID>4</rasd:InstanceID>
<rasd:ResourceSubType>LsiLogic</rasd:ResourceSubType>
<rasd:ResourceType>6</rasd:ResourceType>
</Item> */
}
break;
case OVFResourceType_EthernetAdapter: // 10
{
/* <Item>
<rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
<rasd:Caption>Ethernet adapter on 'VM Network'</rasd:Caption>
<rasd:Connection>VM Network</rasd:Connection>
<rasd:Description>VM Network?</rasd:Description>
<rasd:ElementName>Ethernet adapter</rasd:ElementName>
<rasd:InstanceID>3</rasd:InstanceID>
<rasd:ResourceType>10</rasd:ResourceType>
</Item>
OVF spec DSP 0243 page 21:
"For an Ethernet adapter, this specifies the abstract network connection name
for the virtual machine. All Ethernet adapters that specify the same abstract
network connection name within an OVF package shall be deployed on the same
network. The abstract network connection name shall be listed in the NetworkSection
at the outermost envelope level." */
// make sure we have a matching NetworkSection/Network
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": Invalid connection \"%s\"; cannot find matching NetworkSection/Network element, line %d"),
i.strConnection.c_str(),
i.ulLineNumber);
}
break;
case OVFResourceType_FloppyDrive: // 14
break;
case OVFResourceType_CdDrive: // 15
/* <Item ovf:required="false">
<rasd:Caption>cdrom1</rasd:Caption>
<rasd:InstanceId>7</rasd:InstanceId>
<rasd:ResourceType>15</rasd:ResourceType>
<rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
<rasd:Parent>5</rasd:Parent>
<rasd:AddressOnParent>0</rasd:AddressOnParent>
</Item> */
// I tried to see what happens if I set an ISO for the CD-ROM in VMware Workstation,
// but then the ovftool dies with "Device backing not supported". So I guess if
// VMware can't export ISOs, then we don't need to be able to import them right now.
break;
case OVFResourceType_HardDisk: // 17
{
/* <Item>
<rasd:Caption>Harddisk 1</rasd:Caption>
<rasd:Description>HD</rasd:Description>
<rasd:ElementName>Hard Disk</rasd:ElementName>
<rasd:InstanceID>5</rasd:InstanceID>
<rasd:Parent>4</rasd:Parent>
<rasd:ResourceType>17</rasd:ResourceType>
</Item> */
// look up the hard disk controller element whose InstanceID equals our Parent;
// this is how the connection is specified in OVF
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": Hard disk item with instance ID %d specifies invalid parent %d, line %d"),
i.ulInstanceID,
i.ulParent,
i.ulLineNumber);
bool fFound = false;
// 12345678901234
)
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": Hard disk item with instance ID %d specifies invalid host resource \"%s\", line %d"),
i.ulInstanceID,
i.strHostResource.c_str(),
i.ulLineNumber);
}
break;
case OVFResourceType_UsbController: // 23
/* <Item ovf:required="false">
<rasd:Caption>usb</rasd:Caption>
<rasd:Description>USB Controller</rasd:Description>
<rasd:InstanceId>3</rasd:InstanceId>
<rasd:ResourceType>23</rasd:ResourceType>
<rasd:Address>0</rasd:Address>
<rasd:BusNumber>0</rasd:BusNumber>
</Item> */
break;
case OVFResourceType_SoundCard: // 35
/* <Item ovf:required="false">
<rasd:Caption>sound</rasd:Caption>
<rasd:Description>Sound Card</rasd:Description>
<rasd:InstanceId>10</rasd:InstanceId>
<rasd:ResourceType>35</rasd:ResourceType>
<rasd:ResourceSubType>ensoniq1371</rasd:ResourceSubType>
<rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
<rasd:AddressOnParent>3</rasd:AddressOnParent>
</Item> */
break;
default:
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": Unknown resource type %d in hardware item, line %d"),
i.resourceType,
i.ulLineNumber);
}
}
}
)
{
return setError(VBOX_E_FILE_ERROR,
tr("Error reading \"%s\": missing or invalid 'ovf:id' attribute in operating system section element, line %d"),
pelmThis->getLineNumber());
}
}
// now create the virtual system
return S_OK;
}
// IAppliance public methods
////////////////////////////////////////////////////////////////////////////////
/**
* Appliance initializer.
*
* This loads the given appliance.
* @param
* @return
*/
{
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
/* Weakly reference to a VirtualBox object */
// initialize data
m = new Data;
// see if we can handle this file; for now we insist it has an ".ovf" extension
if ( (!pcszLastDot)
)
)
return setError(VBOX_E_FILE_ERROR,
tr("Appliance file must have .ovf extension"));
try
{
doc);
return setError(VBOX_E_FILE_ERROR,
tr("Root element in OVF file must be \"Envelope\"."));
// OVF has the following rough layout:
/*
-- <References> .... files referenced from other parts of the file, such as VMDK images
-- Metadata, comprised of several section commands
-- virtual machines, either a single <VirtualSystem>, or a <VirtualSystemCollection>
-- optionally <Strings> for localization
*/
// get all "File" child elements of "References" section so we can look up files easily;
// first find the "References" sections so we can look up files
// now go though the sections
return rc;
}
{
return setError(VBOX_E_FILE_ERROR,
x.what());
}
/* Confirm a successful initialization */
return S_OK;
}
{
delete m;
m = NULL;
}
{
if (!aPath)
return E_POINTER;
AutoCaller autoCaller(this);
AutoReadLock alock(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoReadLock alock(this);
size_t i = 0;
++it, ++i)
{
// create a string representing this disk
"%s\t"
"%RI64\t"
"%RI64\t"
"%s\t"
"%s\t"
"%RI64\t"
"%RI64\t"
"%s",
d.iCapacity,
d.iSize,
d.iChunkSize,
d.strCompression.c_str());
// push to safearray
}
return S_OK;
}
STDMETHODIMP Appliance::COMGETTER(VirtualSystemDescriptions)(ComSafeArrayOut(IVirtualSystemDescription*, aVirtualSystemDescriptions))
{
AutoCaller autoCaller(this);
AutoReadLock alock(this);
return S_OK;
}
{
switch (c)
{
case CIMOSType_CIMOS_Unknown: // 0 - Unknown
break;
case CIMOSType_CIMOS_OS2: // 12 - OS/2
break;
case CIMOSType_CIMOS_MSDOS: // 14 - MSDOS
break;
case CIMOSType_CIMOS_WIN3x: // 15 - WIN3x
break;
case CIMOSType_CIMOS_WIN95: // 16 - WIN95
break;
case CIMOSType_CIMOS_WIN98: // 17 - WIN98
break;
case CIMOSType_CIMOS_WINNT: // 18 - WINNT
break;
case CIMOSType_CIMOS_NetWare: // 21 - NetWare
case CIMOSType_CIMOS_NovellOES: // 86 - Novell OES
break;
case CIMOSType_CIMOS_Solaris: // 29 - Solaris
case CIMOSType_CIMOS_SunOS: // 30 - SunOS
break;
case CIMOSType_CIMOS_FreeBSD: // 42 - FreeBSD
break;
case CIMOSType_CIMOS_NetBSD: // 43 - NetBSD
break;
case CIMOSType_CIMOS_QNX: // 48 - QNX
break;
case CIMOSType_CIMOS_Windows2000: // 58 - Windows 2000
break;
case CIMOSType_CIMOS_WindowsMe: // 63 - Windows (R) Me
break;
case CIMOSType_CIMOS_OpenBSD: // 65 - OpenBSD
break;
case CIMOSType_CIMOS_WindowsXP: // 67 - Windows XP
case CIMOSType_CIMOS_WindowsXPEmbedded: // 72 - Windows XP Embedded
case CIMOSType_CIMOS_WindowsEmbeddedforPointofService: // 75 - Windows Embedded for Point of Service
break;
case CIMOSType_CIMOS_MicrosoftWindowsServer2003: // 69 - Microsoft Windows Server 2003
break;
case CIMOSType_CIMOS_MicrosoftWindowsServer2003_64: // 70 - Microsoft Windows Server 2003 64-Bit
break;
case CIMOSType_CIMOS_WindowsXP_64: // 71 - Windows XP 64-Bit
break;
case CIMOSType_CIMOS_WindowsVista: // 73 - Windows Vista
break;
case CIMOSType_CIMOS_WindowsVista_64: // 74 - Windows Vista 64-Bit
break;
case CIMOSType_CIMOS_MicrosoftWindowsServer2008: // 76 - Microsoft Windows Server 2008
break;
case CIMOSType_CIMOS_MicrosoftWindowsServer2008_64: // 77 - Microsoft Windows Server 2008 64-Bit
break;
case CIMOSType_CIMOS_FreeBSD_64: // 78 - FreeBSD 64-Bit
break;
case CIMOSType_CIMOS_RedHatEnterpriseLinux: // 79 - RedHat Enterprise Linux
break;
case CIMOSType_CIMOS_RedHatEnterpriseLinux_64: // 80 - RedHat Enterprise Linux 64-Bit
break;
case CIMOSType_CIMOS_Solaris_64: // 81 - Solaris 64-Bit
break;
case CIMOSType_CIMOS_SUSE: // 82 - SUSE
case CIMOSType_CIMOS_SLES: // 84 - SLES
case CIMOSType_CIMOS_NovellLinuxDesktop: // 87 - Novell Linux Desktop
break;
case CIMOSType_CIMOS_SUSE_64: // 83 - SUSE 64-Bit
case CIMOSType_CIMOS_SLES_64: // 85 - SLES 64-Bit
break;
case CIMOSType_CIMOS_LINUX: // 36 - LINUX
case CIMOSType_CIMOS_SunJavaDesktopSystem: // 88 - Sun Java Desktop System
case CIMOSType_CIMOS_TurboLinux: // 91 - TurboLinux
break;
// case CIMOSType_CIMOS_TurboLinux_64: // 92 - TurboLinux 64-Bit
// case CIMOSType_CIMOS_Linux_64: // 101 - Linux 64-Bit
// osTypeVBox = VBOXOSTYPE_Linux_x64;
// break;
case CIMOSType_CIMOS_Mandriva: // 89 - Mandriva
break;
case CIMOSType_CIMOS_Mandriva_64: // 90 - Mandriva 64-Bit
break;
case CIMOSType_CIMOS_Ubuntu: // 93 - Ubuntu
break;
case CIMOSType_CIMOS_Ubuntu_64: // 94 - Ubuntu 64-Bit
break;
case CIMOSType_CIMOS_Debian: // 95 - Debian
break;
case CIMOSType_CIMOS_Debian_64: // 96 - Debian 64-Bit
break;
case CIMOSType_CIMOS_Linux_2_4_x: // 97 - Linux 2.4.x
break;
case CIMOSType_CIMOS_Linux_2_4_x_64: // 98 - Linux 2.4.x 64-Bit
break;
case CIMOSType_CIMOS_Linux_2_6_x: // 99 - Linux 2.6.x
break;
case CIMOSType_CIMOS_Linux_2_6_x_64: // 100 - Linux 2.6.x 64-Bit
break;
default:
{
/* If we are here we have no clue what OS this should be. Set
to other type as default. */
}
}
}
{
// @todo:
// - Locking
// - COM error handling
// - don't use COM methods but the methods directly (faster, but needs appropriate locking of that objects itself (s. HardDisk2))
// - Appropriate handle errors like not supported file formats
AutoCaller autoCaller(this);
AutoWriteLock(this);
/* Clear any previous virtual system descriptions */
// @todo: have the entries deleted also?
/* We need the default path for storing disk images */
try
{
/* Iterate through all appliances */
++it)
{
/* Guest OS type */
"",
/* VM name */
/* If the there isn't any name specified create a default one out of
* the OS type */
if (nameVBox == "")
"",
nameVBox);
/* Now that we know the OS type, get our internal defaults based on that. */
/* CPU count */
/* @todo: check min/max requirements of VBox (SchemaDefs::Min/MaxCPUCount) */
cpuCountVBox = 1;
"",
/* RAM */
/* @todo: check min/max requirements of VBox (SchemaDefs::Min/MaxGuestRAM) */
if (vsysThis.ullMemorySize == 0)
{
/* If the RAM of the OVF is zero, use our predefined values */
/* VBox stores that in MByte */
}
"",
/* Audio */
/* Currently we set the AC97 always.
@todo: figure out the hardware which could be possible */
"",
"");
/* USB Controller */
/* Network Controller */
// @todo: there is no hardware specification in the OVF file; supposedly the
// hardware will then be determined by the VirtualSystemType element (e.g. "vmx-07")
{
/* Get the default network adapter type for the selected guest OS */
/* Iterate through all abstract networks. We support 8 network
* adapters at the maximum. (@todo: warn if it are more!) */
size_t a = 0;
++nwIt, ++a)
{
pNewDesc->addEntry(VirtualSystemDescriptionType_NetworkAdapter, "", "", toString<ULONG>(nwAdapterVBox));
}
}
/* Floppy Drive */
if (vsysThis.fHasFloppyDrive)
/* CD Drive */
if (vsysThis.fHasCdromDrive)
/* Hard disk Controller */
/* Iterate through all hard disk controllers */
++hdcIt)
{
{
case HardDiskController::IDE:
{
// @todo: figure out the IDE types
/* Use PIIX4 as default */
// IDEControllerType_T hdcController = IDEControllerType_PIIX4;
strType = "PIIX3";
// else // if (!RTStrICmp(hdc.strControllerType.c_str(), "PIIX4"))
// hdcController = IDEControllerType_PIIX4;
strType);
break;
}
case HardDiskController::SATA:
{
// @todo: figure out the SATA types
/* We only support a plain AHCI controller, so use them always */
"AHCI");
break;
}
case HardDiskController::SCSI:
{
// @todo: figure out the SCSI types
/* if (!RTStrICmp(hdc.strControllerType.c_str(), "LsiLogic"))
hdcController = "LsiLogic";
else*/
hdcController = "BusLogic";
break;
}
}
}
/* Hard disks */
{
// @todo:
// - strHref could be empty (construct a new default file name)
// - check that the filename is unique to vbox in any case
/* Iterate through all hard disks ()*/
++itVD)
{
/* Get the associated disk image */
// @todo:
// - figure out all possible vmdk formats we also support
// - figure out if there is a url specifier for vhd already
// - we need a url specifier for the vdi format
)
{
// construct a unique target path
// find the description for the hard disk controller that has the
// same ID as hd.idController
tr("Internal inconsistency looking up hard disk controller."));
// controller to attach to @todo bus?
}
}
}
}
}
{
/* On error we clear the list & return */
//m->virtualSystemDescriptions.clear();
}
return rc;
}
{
AutoCaller autoCaller(this);
AutoReadLock(this);
try
{
/* Create the progress object */
FALSE /* aCancelable */);
/* Initialize our worker task */
//AssertComRCThrowRC (task->autoCaller.rc());
}
{
}
/* Return progress to the caller */
return rc;
}
{
int i = 1;
/* @todo: Maybe too cost-intensive; try to find a lighter way */
{
++i;
}
return S_OK;
}
{
int i = 1;
/* Check if the file exists or if a file with this path is registered
* already */
/* @todo: Maybe too cost-intensive; try to find a lighter way */
while (RTPathExists(tmpName) ||
{
++i;
}
return S_OK;
}
/* static */
{
/// @todo ugly hack, fix ComAssert... (same as in HardDisk2::taskThread)
/* For now we report 2 steps for every virtual system. Later we may add the
progress of the image cloning. */
/* Iterate through all virtual systems of that appliance */
size_t i = 0;
{
/* Catch possible errors */
try
{
/* Guest OS type */
std::list<VirtualSystemDescriptionEntry*> vsdeOS = vsdescThis->findByType(VirtualSystemDescriptionType_OS);
/* Now that we know the base system get our internal defaults based on that. */
/* Create the machine */
/* First get the name */
std::list<VirtualSystemDescriptionEntry*> vsdeName = vsdescThis->findByType(VirtualSystemDescriptionType_Name);
/* CPU count (ignored for now) */
/* @todo: check min/max requirements of VBox (SchemaDefs::Min/MaxCPUCount) */
// EntriesList vsdeCPU = vsd->findByType (VirtualSystemDescriptionType_CPU);
/* RAM */
/* @todo: check min/max requirements of VBox (SchemaDefs::Min/MaxGuestRAM) */
std::list<VirtualSystemDescriptionEntry*> vsdeRAM = vsdescThis->findByType(VirtualSystemDescriptionType_Memory);
/* VRAM */
/* Get the recommended VRAM for this guest OS type */
/* @todo: check min/max requirements of VBox (SchemaDefs::Min/MaxGuestVRAM) */
/* Set the VRAM */
/* Audio Adapter */
std::list<VirtualSystemDescriptionEntry*> vsdeAudioAdapter = vsdescThis->findByType(VirtualSystemDescriptionType_SoundCard);
/* @todo: we support one audio adapter only */
if (vsdeAudioAdapter.size() > 0)
{
{
/* @todo: For now this is preselected, but on Linux for example
more drivers are possible. The user should be able to change
this also. */
#if defined(RT_OS_WINDOWS)
# ifdef VBOX_WITH_WINMM
# else
# endif
#elif defined(RT_OS_LINUX)
# ifdef VBOX_WITH_ALSA
# elif defined(VBOX_WITH_PULSE)
# else
# endif
#elif defined(RT_OS_DARWIN)
#elif defined(RT_OS_SOLARIS)
#endif
}
}
/* USB Controller */
std::list<VirtualSystemDescriptionEntry*> vsdeUSBController = vsdescThis->findByType(VirtualSystemDescriptionType_USBController);
// USB support is enabled if there's at least one such entry; to disable USB support,
// the type of the USB item would have been changed to "ignore"
/* Change the network adapters */
std::list<VirtualSystemDescriptionEntry*> vsdeNW = vsdescThis->findByType(VirtualSystemDescriptionType_NetworkAdapter);
{
/* No network adapters, so we have to disable our default one */
}
else
{
/* Iterate through all network cards. We support 8 network adapters
* at the maximum. (@todo: warn if there are more!) */
size_t a = 0;
++nwIt, ++a)
{
/* Enable the network card & set the adapter type */
/* NAT is set as default */
}
}
/* Floppy drive */
std::list<VirtualSystemDescriptionEntry*> vsdeFloppy = vsdescThis->findByType(VirtualSystemDescriptionType_Floppy);
// Floppy support is enabled if there's at least one such entry; to disable floppy support,
// the type of the floppy item would have been changed to "ignore"
/* CDROM drive */
/* @todo: I can't disable the CDROM. So nothing to do for now */
// std::list<VirtualSystemDescriptionEntry*> vsdeFloppy = vsd->findByType(VirtualSystemDescriptionType_CDROM);
/* Hard disk controller IDE */
std::list<VirtualSystemDescriptionEntry*> vsdeHDCIDE = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskControllerIDE);
/* @todo: we support one IDE controller only */
if (vsdeHDCIDE.size() > 0)
{
// set the appropriate IDE controller in the virtual BIOS of the VM
else
throw setError(VBOX_E_FILE_ERROR,
tr("Invalid IDE controller type \"%s\""),
}
#ifdef VBOX_WITH_AHCI
/* Hard disk controller SATA */
std::list<VirtualSystemDescriptionEntry*> vsdeHDCSATA = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskControllerSATA);
/* @todo: we support one SATA controller only */
if (vsdeHDCSATA.size() > 0)
{
if (hdcVBox == "AHCI")
{
/* For now we have just to enable the AHCI controller. */
}
else
{
/* @todo: set an error if this is other than AHCI */
}
}
#endif /* VBOX_WITH_AHCI */
/* Hard disk controller SCSI */
std::list<VirtualSystemDescriptionEntry*> vsdeHDCSCSI = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskControllerSCSI);
/* @todo: do we support more than one SCSI controller? */
if (vsdeHDCSCSI.size() > 0)
{
/* @todo: revisit when Main support for SCSI is ready */
}
/* Now its time to register the machine before we add any hard disks */
/* Create the hard disks & connect them to the appropriate controllers. */
std::list<VirtualSystemDescriptionEntry*> avsdeHDs = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskImage);
{
/* If in the next block an error occur we have to deregister
try
{
// in order to attach hard disks we need to open a session for the new machine
int result;
/* The disk image has to be on the same place as the OVF file. So
* strip the filename out of the full file path. */
/* Iterate over all given disk images */
++itHD)
{
/* Check if the destination file exists already or the
* destination path is empty. */
if ( !(*pcszDstFilePath)
)
/* This isn't allowed */
throw setError(VBOX_E_FILE_ERROR,
tr("Destination file '%s' exists",
// find the disk from the OVF's disk list
// vsdeHD->strRef contains the disk identifier (e.g. "vmdisk1", which should exist
// in the virtual system's disks map under that ID and also in the global images map
)
tr("Internal inconsistency looking up disk images."));
/* Construct the source file path */
/* Check if the source file exists */
{
/* @todo: we have to create a new one */
}
else
{
/* Make sure all target directories exists */
/* Clone the disk image (this is necessary cause the id has
* to be recreated for the case the same hard disk is
* attached already from a previous import) */
/* First open the existing disk image */
/* We need the format description of the source disk image */
/* Create a new hard disk interface for the destination disk image */
/* Clone the source disk image */
/* We *must* close the source disk image in order to deregister it */
/* Now use the new uuid to attach the disk image to our new machine */
/* For now we assume we have one controller of every type only */
{
//case HardDiskController::SCSI: sbt = StorageBus_SCSI; break; // @todo: not available yet
default: break;
}
}
}
}
{
/* Unregister/Delete the failed machine */
/* @todo: Not sure what to do when there are succesfully
added disk images. Delete them also? For now we leave
them. */
{
/* If there is an open session, close them before doing
anything further. */
}
/* Throw the original error number */
throw aRC;
}
}
}
{
/* @todo: If we are here an error on importing of *one* virtual
system has occured. We didn't break now, but try to import the
other virtual systems. This needs some further discussion. */
}
}
/// @todo ugly hack, fix ComAssert... (same as in HardDisk2::taskThread)
return VINF_SUCCESS;
}
// IVirtualSystemDescription constructor / destructor
////////////////////////////////////////////////////////////////////////////////
struct shutup3 {};
struct VirtualSystemDescription::Data
{
};
{
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
/* Initialize data */
m = new Data();
/* Confirm a successful initialization */
return S_OK;
}
void VirtualSystemDescription::uninit()
{
delete m;
m = NULL;
}
STDMETHODIMP VirtualSystemDescription::GetDescription(ComSafeArrayOut(VirtualSystemDescriptionType_T, aTypes),
{
if (ComSafeArrayOutIsNull(aTypes) ||
return E_POINTER;
AutoCaller autoCaller(this);
AutoReadLock alock(this);
size_t i = 0;
++it, ++i)
{
}
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoWriteLock alock(this);
++it)
{
VirtualSystemDescriptionEntry &e = *it;
{
return S_OK;
}
}
return setError(VBOX_E_OBJECT_NOT_FOUND,
tr("Array item index %d not found"),
index);
}
{
AutoCaller autoCaller(this);
AutoWriteLock alock(this);
return E_INVALIDARG;
size_t i = 0;
++it, ++i)
{
}
return S_OK;
}
const Utf8Str &aOrigValue,
const Utf8Str &aAutoValue,
{
vsde.ulIndex = m->descriptions.size(); // each entry gets an index so the client side can reference them
}
std::list<VirtualSystemDescriptionEntry*> VirtualSystemDescription::findByType(VirtualSystemDescriptionType_T aType)
{
++it)
return vsd;
}
{
++it)
{
{
return &(*it);
break;
}
}
return NULL;
}