VirtualBox

Changeset 28165 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Apr 11, 2010 7:15:06 PM (15 years ago)
Author:
vboxsync
Message:

Main/OVF: import vbox:machine with disks, the rest. Todo some bugfixing.

Location:
trunk/src/VBox/Main
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ApplianceImpl.cpp

    r28162 r28165  
    564564
    565565/**
     566 * Little shortcut to SystemProperties::DefaultHardDiskFolder.
     567 * @param str
     568 * @return
     569 */
     570HRESULT Appliance::getDefaultHardDiskFolder(Utf8Str &str) const
     571{
     572    /* We need the default path for storing disk images */
     573    ComPtr<ISystemProperties> systemProps;
     574    HRESULT rc = mVirtualBox->COMGETTER(SystemProperties)(systemProps.asOutParam());
     575    if (FAILED(rc)) return rc;
     576    Bstr bstrDefaultHardDiskFolder;
     577    rc = systemProps->COMGETTER(DefaultHardDiskFolder)(bstrDefaultHardDiskFolder.asOutParam());
     578    if (FAILED(rc)) return rc;
     579    str = bstrDefaultHardDiskFolder;
     580
     581    return S_OK;
     582}
     583
     584/**
    566585 * Called from the import and export background threads to synchronize the second
    567586 * background disk thread's progress object with the current progress object so
  • trunk/src/VBox/Main/ApplianceImplImport.cpp

    r28162 r28165  
    125125    m->virtualSystemDescriptions.clear();
    126126
    127     /* We need the default path for storing disk images */
    128     ComPtr<ISystemProperties> systemProps;
    129     rc = mVirtualBox->COMGETTER(SystemProperties)(systemProps.asOutParam());
    130     if (FAILED(rc)) return rc;
    131     Bstr bstrDefaultHardDiskLocation;
    132     rc = systemProps->COMGETTER(DefaultHardDiskFolder)(bstrDefaultHardDiskLocation.asOutParam());
     127    Utf8Str strDefaultHardDiskFolder;
     128    rc = getDefaultHardDiskFolder(strDefaultHardDiskFolder);
    133129    if (FAILED(rc)) return rc;
    134130
     
    505501                    //  - we need a url specifier for the vdi format
    506502                    if (   di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#sparse", Utf8Str::CaseInsensitive)
    507                         || di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#compressed", Utf8Str::CaseInsensitive))
     503                        || di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#compressed", Utf8Str::CaseInsensitive)
     504                       )
    508505                    {
    509506                        /* If the href is empty use the VM name as filename */
     
    512509                            strFilename = Utf8StrFmt("%s.vmdk", nameVBox.c_str());
    513510                        /* Construct a unique target path */
    514                         Utf8StrFmt strPath("%ls%c%s",
    515                                            bstrDefaultHardDiskLocation.raw(),
     511                        Utf8StrFmt strPath("%s%c%s",
     512                                           strDefaultHardDiskFolder.raw(),
    516513                                           RTPATH_DELIMITER,
    517514                                           strFilename.c_str());
     
    531528                                                  pController->ulIndex,
    532529                                                  hd.ulAddressOnParent);
    533                         ULONG ulSize = 0;
    534                         if (di.iCapacity != -1)
    535                             ulSize = (ULONG)(di.iCapacity / _1M);
    536                         else if (di.iPopulatedSize != -1)
    537                             ulSize = (ULONG)(di.iPopulatedSize / _1M);
    538                         else if (di.iSize != -1)
    539                             ulSize = (ULONG)(di.iSize / _1M);
    540                         if (ulSize == 0)
    541                             ulSize = 10000;         // assume 10 GB, this is for the progress bar only anyway
    542530                        pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskImage,
    543531                                           hd.strDiskId,
    544532                                           di.strHref,
    545533                                           strPath,
    546                                            ulSize,
     534                                           di.ulSuggestedSizeMB,
    547535                                           strExtraConfig);
    548536                    }
     
    11531141
    11541142            if (vsdescThis->m->pConfig)
    1155                 importVBoxMachine(vsysThis, vsdescThis, pNewMachine, stack);
     1143                importVBoxMachine(vsdescThis, pNewMachine, stack);
    11561144            else
    11571145                importMachineGeneric(vsysThis, vsdescThis, pNewMachine, stack);
     
    12301218
    12311219/**
    1232  *
    1233  * @param vsysThis OVF virtual system containing the VirtualDisksMap. We don't pass that directly
    1234  *                 because it's a typedef which requires the whole ovfreader.h to be included otherwise.
    1235  * @param vsdeHD
    1236  * @param dstHdVBox
     1220 * Imports one disk image. This is common code shared between
     1221 *  --  importMachineGeneric() for the OVF case; in that case the information comes from
     1222 *      the OVF virtual systems;
     1223 *  --  importVBoxMachine(); in that case, the information comes from the <vbox:Machine>
     1224 *      tag.
     1225 *
     1226 * Both ways of describing machines use the OVF disk references section, so in both cases
     1227 * the caller needs to pass in the ovf::DiskImage structure from ovfreader.cpp.
     1228 *
     1229 * As a result, in both cases, if di.strHref is empty, we create a new disk as per the OVF
     1230 * spec, even though this cannot really happen in the vbox:Machine case since such data
     1231 * would never have been exported.
     1232 *
     1233 * This advances stack.pProgress by one operation with the disk's weight.
     1234 *
     1235 * @param di ovfreader.cpp structure describing the disk image from the OVF that is to be imported
     1236 * @param ulSizeMB Size of the disk image (for progress reporting)
     1237 * @param strTargetPath Where to create the target image.
     1238 * @param pTargetHD out: The newly created target disk. This also gets pushed on stack.llHardDisksCreated for cleanup.
    12371239 * @param stack
    12381240 */
    12391241void Appliance::importOneDiskImage(const ovf::DiskImage &di,
    1240                                    uint32_t ulSizeMB,
    12411242                                   const Utf8Str &strTargetPath,
    12421243                                   ComPtr<IMedium> &pTargetHD,
     
    12861287            // advance to the next operation
    12871288            stack.pProgress->SetNextOperation(BstrFmt(tr("Creating virtual disk image '%s'"), strTargetPath.c_str()),
    1288                                               ulSizeMB);     // operation's weight, as set up with the IProgress originally
     1289                                              di.ulSuggestedSizeMB);     // operation's weight, as set up with the IProgress originally
    12891290        }
    12901291        else
     
    13261327            /* Advance to the next operation */
    13271328            stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), strSrcFilePath.c_str()),
    1328                                               ulSizeMB);     // operation's weight, as set up with the IProgress originally);
     1329                                              di.ulSuggestedSizeMB);     // operation's weight, as set up with the IProgress originally);
    13291330        }
    13301331
     
    18451846                ComPtr<IMedium> pTargetHD;
    18461847                importOneDiskImage(di,
    1847                                    vsdeHD->ulSizeMB,
    18481848                                   vsdeHD->strVbox,
    18491849                                   pTargetHD,
     
    19101910 * about what needs cleaning up (to support rollback).
    19111911 *
     1912 * The machine config stored in the settings::MachineConfigFile structure contains the UUIDs of
     1913 * the disk attachments used by the machine when it was exported. We also add vbox:uuid attributes
     1914 * to the OVF disks sections so we can look them up. While importing these UUIDs into a second host
     1915 * will most probably work, reimporting them into the same host will cause conflicts, so we always
     1916 * generate new ones on import. This involves the following:
     1917 *
     1918 *  1)  Scan the machine config for disk attachments.
     1919 *
     1920 *  2)  For each disk attachment found, look up the OVF disk image from the disk references section
     1921 *      and import the disk into VirtualBox, which creates a new UUID for it. In the machine config,
     1922 *      replace the old UUID with the new one.
     1923 *
     1924 *  3)  Create the VirtualBox machine with the modfified machine config.
     1925 *
    19121926 * @param config
    19131927 * @param pNewMachine
    19141928 * @param stack
    19151929 */
    1916 void Appliance::importVBoxMachine(const ovf::VirtualSystem &vsysThis,
    1917                                   ComObjPtr<VirtualSystemDescription> &vsdescThis,
     1930void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis,
    19181931                                  ComPtr<IMachine> &pReturnNewMachine,
    19191932                                  ImportStack &stack)
    19201933{
    19211934    Assert(vsdescThis->m->pConfig);
    1922     const settings::MachineConfigFile &config = *vsdescThis->m->pConfig;
     1935
     1936    // make a deep copy of the machine settings here because we will tinker
     1937    // with it by replacing disk UUIDs
     1938    settings::MachineConfigFile config = *vsdescThis->m->pConfig;
     1939
     1940    Utf8Str strDefaultHardDiskFolder;
     1941    HRESULT rc = getDefaultHardDiskFolder(strDefaultHardDiskFolder);
     1942    if (FAILED(rc)) throw rc;
     1943
     1944    // step 1): scan the machine config for UUIDs
     1945    for (settings::StorageControllersList::iterator sit = config.storageMachine.llStorageControllers.begin();
     1946         sit != config.storageMachine.llStorageControllers.end();
     1947         ++sit)
     1948    {
     1949        settings::StorageController &sc = *sit;
     1950
     1951        for (settings::AttachedDevicesList::iterator dit = sc.llAttachedDevices.begin();
     1952             dit != sc.llAttachedDevices.end();
     1953             ++dit)
     1954        {
     1955            settings::AttachedDevice &d = *dit;
     1956
     1957            if (d.uuid.isEmpty())
     1958                // empty DVD and floppy media
     1959                continue;
     1960
     1961            // convert the Guid to string
     1962            Utf8Str strUuid = d.uuid.toString();
     1963
     1964            // there must be an image in the OVF disk structs with the same UUID
     1965            bool fFound = false;
     1966            for (ovf::DiskImagesMap::const_iterator oit = stack.mapDisks.begin();
     1967                 oit != stack.mapDisks.end();
     1968                 ++oit)
     1969            {
     1970                const ovf::DiskImage &di = oit->second;
     1971
     1972                if (di.uuidVbox == strUuid)
     1973                {
     1974                    Utf8Str strTargetPath(strDefaultHardDiskFolder);
     1975                    strTargetPath.append(RTPATH_DELIMITER);
     1976                    strTargetPath.append(di.strHref);
     1977                    searchUniqueDiskImageFilePath(strTargetPath);
     1978
     1979                    // step 2): import disks and map the old and new UUIDs
     1980                    ComPtr<IMedium> pTargetHD;
     1981                    importOneDiskImage(di,
     1982                                       strTargetPath,
     1983                                       pTargetHD,
     1984                                       stack);
     1985
     1986                    Bstr hdId;
     1987                    rc = pTargetHD->COMGETTER(Id)(hdId.asOutParam());
     1988                    if (FAILED(rc)) throw rc;
     1989
     1990                    // replace the old UUID in the machine config with the new one
     1991                    d.uuid = hdId;
     1992                    fFound = true;
     1993                    break;
     1994                }
     1995            }
     1996
     1997            // no disk with such a UUID found:
     1998            if (!fFound)
     1999                throw setError(E_FAIL,
     2000                               tr("<vbox:Machine> element in OVF contains a medium attachment for the disk image %s but the OVF describes no such image"),
     2001                               strUuid.raw());
     2002        } // for (settings::AttachedDevicesList::const_iterator dit = sc.llAttachedDevices.begin();
     2003    } // for (settings::StorageControllersList::const_iterator sit = config.storageMachine.llStorageControllers.begin();
     2004
     2005    // step 3): create the machine and have it import the config
    19232006
    19242007    // use the name that we computed in the OVF fields to avoid duplicates
     
    19302013
    19312014    ComObjPtr<Machine> pNewMachine;
    1932     HRESULT rc = pNewMachine.createObject();
     2015    rc = pNewMachine.createObject();
    19332016    if (FAILED(rc)) throw rc;
    19342017
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r28162 r28165  
    119119    HRESULT searchUniqueVMName(Utf8Str& aName) const;
    120120    HRESULT searchUniqueDiskImageFilePath(Utf8Str& aName) const;
     121    HRESULT getDefaultHardDiskFolder(Utf8Str &str) const;
    121122    void waitForAsyncProgress(ComObjPtr<Progress> &pProgressThis, ComPtr<IProgress> &pProgressAsync);
    122123    void addWarning(const char* aWarning, ...);
     
    154155    struct ImportStack;
    155156    void importOneDiskImage(const ovf::DiskImage &di,
    156                             uint32_t ulSizeMB,
    157157                            const Utf8Str &strTargetPath,
    158158                            ComPtr<IMedium> &pTargetHD,
     
    162162                              ComPtr<IMachine> &pNewMachine,
    163163                              ImportStack &stack);
    164     void importVBoxMachine(const ovf::VirtualSystem &vsysThis,
    165                            ComObjPtr<VirtualSystemDescription> &vsdescThis,
     164    void importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis,
    166165                           ComPtr<IMachine> &pNewMachine,
    167166                           ImportStack &stack);
     
    192191    Utf8Str strExtraConfig;                 // extra configuration key=value strings (type-dependent)
    193192
    194     uint32_t ulSizeMB;                      // hard disk images only: size of the uncompressed image in MB
     193    uint32_t ulSizeMB;                      // hard disk images only: a copy of ovf::DiskImage::ulSuggestedSizeMB
    195194};
    196195
  • trunk/src/VBox/Main/include/ovfreader.h

    r27918 r28165  
    152152struct DiskImage
    153153{
     154    // fields from /DiskSection/Disk
    154155    iprt::MiniString strDiskId;     // value from DiskSection/Disk/@diskId
    155156    int64_t iCapacity;              // value from DiskSection/Disk/@capacity;
     
    160161    iprt::MiniString strFormat;              // value from DiskSection/Disk/@format
    161162                // typically http://www.vmware.com/specifications/vmdk.html#sparse
     163    iprt::MiniString uuidVbox;      // optional; if the file was exported by VirtualBox >= 3.2,
     164                                    // then this has the UUID with which the disk was registered
    162165
    163166    // fields from /References/File; the spec says the file reference from disk can be empty,
     
    167170    int64_t iChunkSize;             // value from /References/File/@chunkSize (optional, unsupported)
    168171    iprt::MiniString strCompression; // value from /References/File/@compression (optional, can be "gzip" according to spec)
     172
     173    // additional field which has a descriptive size in megabytes derived from the above; this can be used for progress reports
     174    uint32_t ulSuggestedSizeMB;
    169175};
    170176
     
    383389    OVFReader(const iprt::MiniString &path);
    384390
     391    // Data fields
     392    iprt::MiniString            m_strPath;            // file name given to constructor
     393    DiskImagesMap               m_mapDisks;           // map of DiskImage structs, sorted by DiskImage.strDiskId
     394    std::list<VirtualSystem>    m_llVirtualSystems;   // list of virtual systems, created by and valid after read()
     395
     396private:
     397    xml::Document               m_doc;
     398
    385399    void LoopThruSections(const xml::ElementNode *pReferencesElem, const xml::ElementNode *pCurElem);
    386400    void HandleDiskSection(const xml::ElementNode *pReferencesElem, const xml::ElementNode *pSectionElem);
    387401    void HandleNetworkSection(const xml::ElementNode *pSectionElem);
    388402    void HandleVirtualSystemContent(const xml::ElementNode *pContentElem);
    389 
    390     // Data fields
    391     iprt::MiniString            m_strPath;            // file name given to constructor
    392     DiskImagesMap               m_mapDisks;           // map of DiskImage structs, sorted by DiskImage.strDiskId
    393     std::list<VirtualSystem>    m_llVirtualSystems;   // list of virtual systems, created by and valid after read()
    394 
    395 private:
    396     xml::Document               m_doc;
    397403};
    398404
  • trunk/src/VBox/Main/xml/Settings.cpp

    r28127 r28165  
    122122{
    123123    Data()
    124         : pParser(NULL),
    125           pDoc(NULL),
     124        : pDoc(NULL),
    126125          pelmRoot(NULL),
    127126          sv(SettingsVersion_Null),
     
    137136    bool                    fFileExists;
    138137
    139     xml::XmlFileParser      *pParser;
    140138    xml::Document           *pDoc;
    141139    xml::ElementNode        *pelmRoot;
     
    164162            pelmRoot = NULL;
    165163        }
    166 
    167         if (pParser)
    168         {
    169             delete pParser;
    170             pParser = NULL;
    171         }
    172164    }
    173165};
     
    228220        m->strFilename = *pstrFilename;
    229221
    230         m->pParser = new xml::XmlFileParser;
     222        xml::XmlFileParser parser;
    231223        m->pDoc = new xml::Document;
    232         m->pParser->read(*pstrFilename,
    233                         *m->pDoc);
     224        parser.read(*pstrFilename,
     225                    *m->pDoc);
    234226
    235227        m->fFileExists = true;
     
    39423934    }
    39433935}
     3936
  • trunk/src/VBox/Main/xml/ovfreader.cpp

    r27918 r28165  
    183183                d.iPopulatedSize = -1;
    184184
     185            // optional vbox:uuid attribute (if OVF was exported by VirtualBox != 3.2)
     186            pelmDisk->getAttributeValue("vbox:uuid", d.uuidVbox);
     187
    185188            const char *pcszFileRef;
    186189            if (pelmDisk->getAttributeValue("fileRef", pcszFileRef)) // optional
     
    227230                                pcszBad,
    228231                                pelmDisk->getLineNumber());
     232
     233        // suggest a size in megabytes to help callers with progress reports
     234        d.ulSuggestedSizeMB = 0;
     235        if (d.iCapacity != -1)
     236            d.ulSuggestedSizeMB = d.iCapacity / _1M;
     237        else if (d.iPopulatedSize != -1)
     238            d.ulSuggestedSizeMB = d.iPopulatedSize / _1M;
     239        else if (d.iSize != -1)
     240            d.ulSuggestedSizeMB = d.iSize / _1M;
     241        if (d.ulSuggestedSizeMB == 0)
     242            d.ulSuggestedSizeMB = 10000;         // assume 10 GB, this is for the progress bar only anyway
    229243
    230244        m_mapDisks[d.strDiskId] = d;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette