VirtualBox

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


Ignore:
Timestamp:
Apr 11, 2010 12:44:21 PM (15 years ago)
Author:
vboxsync
Message:

Main/OVF: isolate disk import code from other import code; clean up progress handling

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

Legend:

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

    r27918 r28162  
    628628}
    629629
    630 void Appliance::disksWeight(uint32_t &ulTotalMB, uint32_t &cDisks) const
    631 {
    632     ulTotalMB = 0;
    633     cDisks = 0;
    634     /* Weigh the disk images according to their sizes */
     630/**
     631 * Refreshes the cDisks and ulTotalDisksMB members in the instance data.
     632 * Requires that virtual system descriptions are present.
     633 */
     634void Appliance::disksWeight()
     635{
     636    m->ulTotalDisksMB = 0;
     637    m->cDisks = 0;
     638    // weigh the disk images according to their sizes
    635639    list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
    636640    for (it = m->virtualSystemDescriptions.begin();
     
    647651        {
    648652            const VirtualSystemDescriptionEntry *pHD = *itH;
    649             ulTotalMB += pHD->ulSizeMB;
    650             ++cDisks;
     653            m->ulTotalDisksMB += pHD->ulSizeMB;
     654            ++m->cDisks;
    651655        }
    652656    }
     
    654658}
    655659
    656 HRESULT Appliance::setUpProgressFS(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription)
     660HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
     661                                 const Bstr &bstrDescription,
     662                                 SetUpProgressMode mode)
    657663{
    658664    HRESULT rc;
     
    661667    pProgress.createObject();
    662668
    663     /* Weigh the disk images according to their sizes */
    664     uint32_t ulTotalMB;
    665     uint32_t cDisks;
    666     disksWeight(ulTotalMB, cDisks);
    667 
    668     ULONG cOperations = 1 + cDisks;     // one op per disk plus 1 for the XML
    669 
     669    // compute the disks weight (this sets ulTotalDisksMB and cDisks in the instance data)
     670    disksWeight();
     671
     672    ULONG cOperations;
    670673    ULONG ulTotalOperationsWeight;
    671     if (ulTotalMB)
    672     {
    673         m->ulWeightPerOperation = (ULONG)((double)ulTotalMB * 1  / 100);    // use 1% of the progress for the XML
    674         ulTotalOperationsWeight = ulTotalMB + m->ulWeightPerOperation;
     674
     675    cOperations =   1               // one for XML setup
     676                  + m->cDisks;      // plus one per disk
     677    if (m->ulTotalDisksMB)
     678    {
     679        m->ulWeightPerOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100);    // use 1% of the progress for the XML
     680        ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightPerOperation;
    675681    }
    676682    else
    677683    {
    678684        // no disks to export:
     685        m->ulWeightPerOperation = 1;
    679686        ulTotalOperationsWeight = 1;
    680         m->ulWeightPerOperation = 1;
     687    }
     688
     689    switch (mode)
     690    {
     691        case Regular:
     692        break;
     693
     694        case ImportS3:
     695        {
     696            cOperations += 1 + 1;     // another one for the manifest file & another one for the import
     697            ulTotalOperationsWeight = m->ulTotalDisksMB;
     698            if (!m->ulTotalDisksMB)
     699                // no disks to export:
     700                ulTotalOperationsWeight = 1;
     701
     702            ULONG ulImportWeight = (ULONG)((double)ulTotalOperationsWeight * 50  / 100);  // use 50% for import
     703            ulTotalOperationsWeight += ulImportWeight;
     704
     705            m->ulWeightPerOperation = ulImportWeight; /* save for using later */
     706
     707            ULONG ulInitWeight = (ULONG)((double)ulTotalOperationsWeight * 0.1  / 100);  // use 0.1% for init
     708            ulTotalOperationsWeight += ulInitWeight;
     709        }
     710        break;
     711
     712        case WriteS3:
     713        {
     714            cOperations += 1 + 1;     // another one for the mf & another one for temporary creation
     715
     716            if (m->ulTotalDisksMB)
     717            {
     718                m->ulWeightPerOperation = (ULONG)((double)m->ulTotalDisksMB * 1  / 100);    // use 1% of the progress for OVF file upload (we didn't know the size at this point)
     719                ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightPerOperation;
     720            }
     721            else
     722            {
     723                // no disks to export:
     724                ulTotalOperationsWeight = 1;
     725                m->ulWeightPerOperation = 1;
     726            }
     727            ULONG ulOVFCreationWeight = (ULONG)((double)ulTotalOperationsWeight * 50.0 / 100.0); /* Use 50% for the creation of the OVF & the disks */
     728            ulTotalOperationsWeight += ulOVFCreationWeight;
     729        }
     730        break;
    681731    }
    682732
    683733    Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightPerOperation = %d\n",
    684          ulTotalMB, cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));
     734         m->ulTotalDisksMB, m->cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));
    685735
    686736    rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this),
     
    691741                         bstrDescription, // CBSTR bstrFirstOperationDescription,
    692742                         m->ulWeightPerOperation); // ULONG ulFirstOperationWeight,
    693     return rc;
    694 }
    695 
    696 HRESULT Appliance::setUpProgressImportS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription)
    697 {
    698     HRESULT rc;
    699 
    700     /* Create the progress object */
    701     pProgress.createObject();
    702 
    703     /* Weigh the disk images according to their sizes */
    704     uint32_t ulTotalMB;
    705     uint32_t cDisks;
    706     disksWeight(ulTotalMB, cDisks);
    707 
    708     ULONG cOperations = 1 + 1 + 1 + cDisks;     // one op per disk plus 1 for init, plus 1 for the manifest file & 1 plus for the import */
    709 
    710     ULONG ulTotalOperationsWeight = ulTotalMB;
    711     if (!ulTotalOperationsWeight)
    712         // no disks to export:
    713         ulTotalOperationsWeight = 1;
    714 
    715     ULONG ulImportWeight = (ULONG)((double)ulTotalOperationsWeight * 50  / 100);  // use 50% for import
    716     ulTotalOperationsWeight += ulImportWeight;
    717 
    718     m->ulWeightPerOperation = ulImportWeight; /* save for using later */
    719 
    720     ULONG ulInitWeight = (ULONG)((double)ulTotalOperationsWeight * 0.1  / 100);  // use 0.1% for init
    721     ulTotalOperationsWeight += ulInitWeight;
    722 
    723     Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightPerOperation = %d\n",
    724          ulTotalMB, cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));
    725 
    726     rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this),
    727                          bstrDescription,
    728                          TRUE /* aCancelable */,
    729                          cOperations, // ULONG cOperations,
    730                          ulTotalOperationsWeight, // ULONG ulTotalOperationsWeight,
    731                          Bstr(tr("Init")), // CBSTR bstrFirstOperationDescription,
    732                          ulInitWeight); // ULONG ulFirstOperationWeight,
    733     return rc;
    734 }
    735 
    736 HRESULT Appliance::setUpProgressWriteS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription)
    737 {
    738     HRESULT rc;
    739 
    740     /* Create the progress object */
    741     pProgress.createObject();
    742 
    743     /* Weigh the disk images according to their sizes */
    744     uint32_t ulTotalMB;
    745     uint32_t cDisks;
    746     disksWeight(ulTotalMB, cDisks);
    747 
    748     ULONG cOperations = 1 + 1 + 1 + cDisks;     // one op per disk plus 1 for the OVF, plus 1 for the mf & 1 plus to the temporary creation */
    749 
    750     ULONG ulTotalOperationsWeight;
    751     if (ulTotalMB)
    752     {
    753         m->ulWeightPerOperation = (ULONG)((double)ulTotalMB * 1  / 100);    // use 1% of the progress for OVF file upload (we didn't know the size at this point)
    754         ulTotalOperationsWeight = ulTotalMB + m->ulWeightPerOperation;
    755     }
    756     else
    757     {
    758         // no disks to export:
    759         ulTotalOperationsWeight = 1;
    760         m->ulWeightPerOperation = 1;
    761     }
    762     ULONG ulOVFCreationWeight = (ULONG)((double)ulTotalOperationsWeight * 50.0 / 100.0); /* Use 50% for the creation of the OVF & the disks */
    763     ulTotalOperationsWeight += ulOVFCreationWeight;
    764 
    765     Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightPerOperation = %d\n",
    766          ulTotalMB, cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));
    767 
    768     rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this),
    769                          bstrDescription,
    770                          TRUE /* aCancelable */,
    771                          cOperations, // ULONG cOperations,
    772                          ulTotalOperationsWeight, // ULONG ulTotalOperationsWeight,
    773                          bstrDescription, // CBSTR bstrFirstOperationDescription,
    774                          ulOVFCreationWeight); // ULONG ulFirstOperationWeight,
    775743    return rc;
    776744}
  • trunk/src/VBox/Main/ApplianceImplExport.cpp

    r28150 r28162  
    610610                                    aLocInfo.strPath.c_str());
    611611
    612         /* todo: This progress init stuff should be done a little bit more generic */
    613         if (aLocInfo.storageType == VFSType_File)
    614             rc = setUpProgressFS(aProgress, progressDesc);
    615         else
    616             rc = setUpProgressWriteS3(aProgress, progressDesc);
     612        rc = setUpProgress(aProgress, progressDesc, (aLocInfo.storageType == VFSType_File) ? Regular : WriteS3);
    617613
    618614        /* Initialize our worker task */
  • trunk/src/VBox/Main/ApplianceImplImport.cpp

    r28152 r28162  
    631631HRESULT Appliance::readImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress)
    632632{
    633     BstrFmt bstrDesc = BstrFmt(tr("Read appliance '%s'"),
     633    BstrFmt bstrDesc = BstrFmt(tr("Reading appliance '%s'"),
    634634                               aLocInfo.strPath.c_str());
    635635    HRESULT rc;
     
    929929HRESULT Appliance::importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress)
    930930{
    931     Bstr progressDesc = BstrFmt(tr("Import appliance '%s'"),
     931    Bstr progressDesc = BstrFmt(tr("Importing appliance '%s'"),
    932932                                aLocInfo.strPath.c_str());
    933933    HRESULT rc = S_OK;
    934934
    935     /* todo: This progress init stuff should be done a little bit more generic */
    936     if (aLocInfo.storageType == VFSType_File)
    937         rc = setUpProgressFS(aProgress, progressDesc);
    938     else
    939         rc = setUpProgressImportS3(aProgress, progressDesc);
     935    rc = setUpProgress(aProgress,
     936                       progressDesc,
     937                       (aLocInfo.storageType == VFSType_File) ? Regular : ImportS3);
    940938    if (FAILED(rc)) throw rc;
    941939
     
    960958    // input pointers
    961959    const LocationInfo          &locInfo;           // ptr to location info from Appliance::importFS()
     960    Utf8Str                     strSourceDir;       // directory where source files reside
    962961    const ovf::DiskImagesMap    &mapDisks;          // ptr to disks map in OVF
    963962    ComObjPtr<Progress>         &pProgress;         // progress object passed into Appliance::importFS()
     
    981980          fSessionOpen(false)
    982981    {
     982        // disk images have to be on the same place as the OVF file. So
     983        // strip the filename out of the full file path
     984        strSourceDir = aLocInfo.strPath;
     985        strSourceDir.stripFilename();
    983986    }
    984987};
    985988
    986989/**
    987  * Actual worker code for importing OVF data into VirtualBox. This is called from Appliance::taskThreadImportOrExport()
    988  * and therefore runs on the OVF import worker thread. This runs in two contexts:
    989  *
    990  * 1) in a first worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl();
    991  *
    992  * 2) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which
    993  *    called Appliance::importS3(), which called Appliance::importImpl(), which then called this.
    994  *
    995  * @param pTask
     990 * Checks if a manifest file exists in the given location and, if so, verifies
     991 * that the relevant files (the OVF XML and the disks referenced by it, as
     992 * represented by the VirtualSystemDescription instances contained in this appliance)
     993 * match it. Requires a previous read() and interpret().
     994 *
     995 * @param locInfo
     996 * @param reader
    996997 * @return
    997998 */
    998 HRESULT Appliance::importFS(const LocationInfo &locInfo,
    999                             ComObjPtr<Progress> &pProgress)
     999HRESULT Appliance::manifestVerify(const LocationInfo &locInfo,
     1000                                  const ovf::OVFReader &reader)
    10001001{
    1001     LogFlowFuncEnter();
    1002     LogFlowFunc(("Appliance %p\n", this));
    1003 
    1004     AutoCaller autoCaller(this);
    1005     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    1006 
    1007     AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
    1008 
    1009     if (!isApplianceIdle())
    1010         return E_ACCESSDENIED;
    1011 
    1012     Assert(!pProgress.isNull());
    1013 
    1014     // Change the appliance state so we can safely leave the lock while doing time-consuming
    1015     // disk imports; also the below method calls do all kinds of locking which conflicts with
    1016     // the appliance object lock
    1017     m->state = Data::ApplianceImporting;
    1018     appLock.release();
    1019 
    10201002    HRESULT rc = S_OK;
    10211003
    1022     const ovf::OVFReader &reader = *m->pReader;
    1023     // this is safe to access because this thread only gets started
    1024     // if pReader != NULL
    1025 
    1026     // rollback for errors:
    1027     ImportStack stack(locInfo, reader.m_mapDisks, pProgress);
    1028     /* If a manifest file exists, verify the content. Therefore we need all
    1029      * files which are referenced by the OVF & the OVF itself */
    10301004    Utf8Str strMfFile = manifestFileName(locInfo.strPath);
    1031     list<Utf8Str> filesList;
    10321005    if (RTPathExists(strMfFile.c_str()))
    10331006    {
     1007        list<Utf8Str> filesList;
    10341008        Utf8Str strSrcDir(locInfo.strPath);
    10351009        strSrcDir.stripFilename();
    1036         /* Add every disks of every virtual system to an internal list */
     1010        // add every disks of every virtual system to an internal list
    10371011        list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
    10381012        for (it = m->virtualSystemDescriptions.begin();
     
    10481022            {
    10491023                VirtualSystemDescriptionEntry *vsdeHD = *itH;
    1050                 /* Find the disk from the OVF's disk list */
     1024                // find the disk from the OVF's disk list
    10511025                ovf::DiskImagesMap::const_iterator itDiskImage = reader.m_mapDisks.find(vsdeHD->strRef);
    10521026                const ovf::DiskImage &di = itDiskImage->second;
     
    10551029            }
    10561030        }
    1057         /* Create the test list */
    1058         PRTMANIFESTTEST pTestList = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST)*(filesList.size()+1));
     1031
     1032        // create the test list
     1033        PRTMANIFESTTEST pTestList = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST) * (filesList.size() + 1));
    10591034        pTestList[0].pszTestFile = (char*)locInfo.strPath.c_str();
    10601035        pTestList[0].pszTestDigest = (char*)m->strOVFSHA1Digest.c_str();
     
    10711046            pTestList[i].pszTestDigest = pszDigest;
    10721047        }
     1048
     1049        // this call can take a very long time
    10731050        size_t cIndexOnError;
    1074         vrc = RTManifestVerify(strMfFile.c_str(), pTestList, filesList.size() + 1, &cIndexOnError);
    1075         if (vrc == VERR_MANIFEST_DIGEST_MISMATCH)
    1076             rc = setError(VBOX_E_FILE_ERROR,
    1077                           tr("The SHA1 digest of '%s' doesn't match to the one in '%s'"),
    1078                           RTPathFilename(pTestList[cIndexOnError].pszTestFile),
    1079                           RTPathFilename(strMfFile.c_str()));
    1080         else if (RT_FAILURE(vrc))
    1081             rc = setError(VBOX_E_FILE_ERROR,
    1082                           tr("Couldn't verify the content of '%s' against the available files (%Rrc)"),
    1083                           RTPathFilename(strMfFile.c_str()),
    1084                           vrc);
    1085         /* Cleanup */
     1051        vrc = RTManifestVerify(strMfFile.c_str(),
     1052                               pTestList,
     1053                               filesList.size() + 1,
     1054                               &cIndexOnError);
     1055
     1056        // clean up
    10861057        for (size_t j = 1;
    10871058             j < filesList.size();
     
    10891060            RTStrFree(pTestList[j].pszTestDigest);
    10901061        RTMemFree(pTestList);
    1091         if (FAILED(rc)) return rc;
    1092     }
    1093 
    1094     rc = stack.pSession.createInprocObject(CLSID_Session);
    1095     if (FAILED(rc)) return rc;
    1096 
    1097     list<ovf::VirtualSystem>::const_iterator it;
    1098     list< ComObjPtr<VirtualSystemDescription> >::const_iterator it1;
    1099     /* Iterate through all virtual systems of that appliance */
    1100     size_t i = 0;
    1101     for (it = reader.m_llVirtualSystems.begin(),
    1102             it1 = m->virtualSystemDescriptions.begin();
    1103          it != reader.m_llVirtualSystems.end();
    1104          ++it, ++it1, ++i)
    1105     {
    1106         const ovf::VirtualSystem &vsysThis = *it;
    1107         ComObjPtr<VirtualSystemDescription> vsdescThis = (*it1);
    1108 
    1109         ComPtr<IMachine> pNewMachine;
    1110 
    1111         /* Catch possible errors */
    1112         try
     1062
     1063        if (vrc == VERR_MANIFEST_DIGEST_MISMATCH)
     1064            rc = setError(VBOX_E_FILE_ERROR,
     1065                          tr("The SHA1 digest of '%s' does not match the one in '%s'"),
     1066                          RTPathFilename(pTestList[cIndexOnError].pszTestFile),
     1067                          RTPathFilename(strMfFile.c_str()));
     1068        else if (RT_FAILURE(vrc))
     1069            rc = setError(VBOX_E_FILE_ERROR,
     1070                          tr("Could not verify the content of '%s' against the available files (%Rrc)"),
     1071                          RTPathFilename(strMfFile.c_str()),
     1072                          vrc);
     1073    }
     1074
     1075    return rc;
     1076}
     1077
     1078/**
     1079 * Actual worker code for importing OVF data into VirtualBox. This is called from Appliance::taskThreadImportOrExport()
     1080 * and therefore runs on the OVF import worker thread. This runs in two contexts:
     1081 *
     1082 * 1) in a first worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl();
     1083 *
     1084 * 2) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which
     1085 *    called Appliance::importS3(), which called Appliance::importImpl(), which then called this.
     1086 *
     1087 * @param pTask
     1088 * @return
     1089 */
     1090HRESULT Appliance::importFS(const LocationInfo &locInfo,
     1091                            ComObjPtr<Progress> &pProgress)
     1092{
     1093    LogFlowFuncEnter();
     1094    LogFlowFunc(("Appliance %p\n", this));
     1095
     1096    AutoCaller autoCaller(this);
     1097    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     1098
     1099    AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
     1100
     1101    if (!isApplianceIdle())
     1102        return E_ACCESSDENIED;
     1103
     1104    Assert(!pProgress.isNull());
     1105
     1106    // Change the appliance state so we can safely leave the lock while doing time-consuming
     1107    // disk imports; also the below method calls do all kinds of locking which conflicts with
     1108    // the appliance object lock
     1109    m->state = Data::ApplianceImporting;
     1110    appLock.release();
     1111
     1112    HRESULT rc = S_OK;
     1113
     1114    const ovf::OVFReader &reader = *m->pReader;
     1115    // this is safe to access because this thread only gets started
     1116    // if pReader != NULL
     1117
     1118    // rollback for errors:
     1119    ImportStack stack(locInfo, reader.m_mapDisks, pProgress);
     1120
     1121    try
     1122    {
     1123        // if a manifest file exists, verify the content; we then need all files which are referenced by the OVF & the OVF itself
     1124        rc = manifestVerify(locInfo, reader);
     1125        if (FAILED(rc)) throw rc;
     1126
     1127        // create a session for the machine + disks we manipulate below
     1128        rc = stack.pSession.createInprocObject(CLSID_Session);
     1129        if (FAILED(rc)) throw rc;
     1130
     1131        list<ovf::VirtualSystem>::const_iterator it;
     1132        list< ComObjPtr<VirtualSystemDescription> >::const_iterator it1;
     1133        /* Iterate through all virtual systems of that appliance */
     1134        size_t i = 0;
     1135        for (it = reader.m_llVirtualSystems.begin(),
     1136                it1 = m->virtualSystemDescriptions.begin();
     1137             it != reader.m_llVirtualSystems.end();
     1138             ++it, ++it1, ++i)
    11131139        {
     1140            const ovf::VirtualSystem &vsysThis = *it;
     1141            ComObjPtr<VirtualSystemDescription> vsdescThis = (*it1);
     1142
     1143            ComPtr<IMachine> pNewMachine;
     1144
    11141145            // there are two ways in which we can create a vbox machine from OVF:
    11151146            // -- either this OVF was written by vbox 3.2 or later, in which case there is a <vbox:Machine> element
     
    11221153
    11231154            if (vsdescThis->m->pConfig)
    1124                 importVBoxMachine(vsdescThis, pNewMachine, stack);
     1155                importVBoxMachine(vsysThis, vsdescThis, pNewMachine, stack);
    11251156            else
    11261157                importMachineGeneric(vsysThis, vsdescThis, pNewMachine, stack);
    1127         }
    1128         catch (HRESULT aRC)
    1129         {
    1130             rc = aRC;
    1131         }
    1132 
    1133         if (FAILED(rc))
    1134             break;
    1135 
    1136     } // for (it = pAppliance->m->llVirtualSystems.begin(),
     1158
     1159        } // for (it = pAppliance->m->llVirtualSystems.begin() ...
     1160    }
     1161    catch (HRESULT rc2)
     1162    {
     1163        rc = rc2;
     1164    }
    11371165
    11381166    if (FAILED(rc))
     
    11991227
    12001228    return rc;
     1229}
     1230
     1231/**
     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
     1237 * @param stack
     1238 */
     1239void Appliance::importOneDiskImage(const ovf::DiskImage &di,
     1240                                   uint32_t ulSizeMB,
     1241                                   const Utf8Str &strTargetPath,
     1242                                   ComPtr<IMedium> &pTargetHD,
     1243                                   ImportStack &stack)
     1244{
     1245    ComPtr<IMedium> pSourceHD;
     1246    bool fSourceHdNeedsClosing = false;
     1247
     1248    try
     1249    {
     1250        // destination file must not exist
     1251        if (    strTargetPath.isEmpty()
     1252             || RTPathExists(strTargetPath.c_str())
     1253           )
     1254            /* This isn't allowed */
     1255            throw setError(VBOX_E_FILE_ERROR,
     1256                           tr("Destination file '%s' exists"),
     1257                           strTargetPath.c_str());
     1258
     1259        const Utf8Str &strSourceOVF = di.strHref;
     1260
     1261        // Make sure target directory exists
     1262        HRESULT rc = VirtualBox::ensureFilePathExists(strTargetPath.c_str());
     1263        if (FAILED(rc))
     1264            throw rc;
     1265
     1266        // subprogress object for hard disk
     1267        ComPtr<IProgress> pProgress2;
     1268
     1269        /* If strHref is empty we have to create a new file */
     1270        if (strSourceOVF.isEmpty())
     1271        {
     1272            // which format to use?
     1273            Bstr srcFormat = L"VDI";
     1274            if (   di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#sparse", Utf8Str::CaseInsensitive)
     1275                || di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#compressed", Utf8Str::CaseInsensitive)
     1276            )
     1277                srcFormat = L"VMDK";
     1278            // create an empty hard disk
     1279            rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(strTargetPath), pTargetHD.asOutParam());
     1280            if (FAILED(rc)) throw rc;
     1281
     1282            // create a dynamic growing disk image with the given capacity
     1283            rc = pTargetHD->CreateBaseStorage(di.iCapacity / _1M, MediumVariant_Standard, pProgress2.asOutParam());
     1284            if (FAILED(rc)) throw rc;
     1285
     1286            // advance to the next operation
     1287            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        }
     1290        else
     1291        {
     1292            // construct source file path
     1293            Utf8StrFmt strSrcFilePath("%s%c%s", stack.strSourceDir.c_str(), RTPATH_DELIMITER, strSourceOVF.c_str());
     1294            // source path must exist
     1295            if (!RTPathExists(strSrcFilePath.c_str()))
     1296                throw setError(VBOX_E_FILE_ERROR,
     1297                               tr("Source virtual disk image file '%s' doesn't exist"),
     1298                               strSrcFilePath.c_str());
     1299
     1300            // Clone the disk image (this is necessary cause the id has
     1301            // to be recreated for the case the same hard disk is
     1302            // attached already from a previous import)
     1303
     1304            // First open the existing disk image
     1305            rc = mVirtualBox->OpenHardDisk(Bstr(strSrcFilePath),
     1306                                        AccessMode_ReadOnly,
     1307                                        false,
     1308                                        NULL,
     1309                                        false,
     1310                                        NULL,
     1311                                        pSourceHD.asOutParam());
     1312            if (FAILED(rc)) throw rc;
     1313            fSourceHdNeedsClosing = true;
     1314
     1315            /* We need the format description of the source disk image */
     1316            Bstr srcFormat;
     1317            rc = pSourceHD->COMGETTER(Format)(srcFormat.asOutParam());
     1318            if (FAILED(rc)) throw rc;
     1319            /* Create a new hard disk interface for the destination disk image */
     1320            rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(strTargetPath), pTargetHD.asOutParam());
     1321            if (FAILED(rc)) throw rc;
     1322            /* Clone the source disk image */
     1323            rc = pSourceHD->CloneTo(pTargetHD, MediumVariant_Standard, NULL, pProgress2.asOutParam());
     1324            if (FAILED(rc)) throw rc;
     1325
     1326            /* Advance to the next operation */
     1327            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        }
     1330
     1331        // now wait for the background disk operation to complete; this throws HRESULTs on error
     1332        waitForAsyncProgress(stack.pProgress, pProgress2);
     1333
     1334        if (fSourceHdNeedsClosing)
     1335        {
     1336            rc = pSourceHD->Close();
     1337            if (FAILED(rc)) throw rc;
     1338            fSourceHdNeedsClosing = false;
     1339        }
     1340
     1341        stack.llHardDisksCreated.push_back(pTargetHD);
     1342    }
     1343    catch (...)
     1344    {
     1345        if (fSourceHdNeedsClosing)
     1346            pSourceHD->Close();
     1347
     1348        throw;
     1349    }
    12011350}
    12021351
     
    16101759                    {
    16111760                        pController = &kt->second;
     1761                        break;
    16121762                    }
    16131763                }
     
    16151765                if (!pController)
    16161766                    throw setError(VBOX_E_FILE_ERROR,
    1617                                     tr("OVF wants a CD-ROM drive but cannot find IDE controller, which is required in this version of VirtualBox"));
     1767                                   tr("OVF wants a CD-ROM drive but cannot find IDE controller, which is required in this version of VirtualBox"));
    16181768
    16191769                // this is for rollback later
     
    16631813        // If there's an error here we need to close the session, so
    16641814        // we need another try/catch block.
    1665         ComPtr<IMedium> srcHdVBox;
    1666         bool fSourceHdNeedsClosing = false;
    1667 
    16681815        try
    16691816        {
     
    16731820            if (FAILED(rc)) throw rc;
    16741821            stack.fSessionOpen = true;
    1675 
    1676             /* The disk image has to be on the same place as the OVF file. So
    1677              * strip the filename out of the full file path. */
    1678             Utf8Str strSrcDir(stack.locInfo.strPath);
    1679             strSrcDir.stripFilename();
    16801822
    16811823            /* Iterate over all given disk images */
     
    16871829                VirtualSystemDescriptionEntry *vsdeHD = *itHD;
    16881830
    1689                 /* Check if the destination file exists already or the
    1690                     * destination path is empty. */
    1691                 if (    vsdeHD->strVbox.isEmpty()
    1692                      || RTPathExists(vsdeHD->strVbox.c_str())
    1693                    )
    1694                     /* This isn't allowed */
    1695                     throw setError(VBOX_E_FILE_ERROR,
    1696                                    tr("Destination file '%s' exists"),
    1697                                    vsdeHD->strVbox.c_str());
    1698 
    1699                 /* Find the disk from the OVF's disk list */
    1700                 ovf::DiskImagesMap::const_iterator itDiskImage = stack.mapDisks.find(vsdeHD->strRef);
    17011831                // vsdeHD->strRef contains the disk identifier (e.g. "vmdisk1"), which should exist
    17021832                // in the virtual system's disks map under that ID and also in the global images map
    17031833                ovf::VirtualDisksMap::const_iterator itVirtualDisk = vsysThis.mapVirtualDisks.find(vsdeHD->strRef);
    1704 
    1705                 if (    itDiskImage == stack.mapDisks.end()
    1706                      || itVirtualDisk == vsysThis.mapVirtualDisks.end()
     1834                // and find the disk from the OVF's disk list
     1835                ovf::DiskImagesMap::const_iterator itDiskImage = stack.mapDisks.find(vsdeHD->strRef);
     1836                if (    (itVirtualDisk == vsysThis.mapVirtualDisks.end())
     1837                     || (itDiskImage == stack.mapDisks.end())
    17071838                   )
    17081839                    throw setError(E_FAIL,
     
    17121843                const ovf::VirtualDisk &vd = itVirtualDisk->second;
    17131844
    1714                 /* Make sure all target directories exists */
    1715                 rc = VirtualBox::ensureFilePathExists(vsdeHD->strVbox.c_str());
    1716                 if (FAILED(rc))
    1717                     throw rc;
    1718 
    1719                 // subprogress object for hard disk
    1720                 ComPtr<IProgress> pProgress2;
    1721 
    1722                 ComPtr<IMedium> dstHdVBox;
    1723                 /* If strHref is empty we have to create a new file */
    1724                 if (di.strHref.isEmpty())
    1725                 {
    1726                     /* Which format to use? */
    1727                     Bstr srcFormat = L"VDI";
    1728                     if (   di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#sparse", Utf8Str::CaseInsensitive)
    1729                         || di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#compressed", Utf8Str::CaseInsensitive))
    1730                         srcFormat = L"VMDK";
    1731                     /* Create an empty hard disk */
    1732                     rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(vsdeHD->strVbox), dstHdVBox.asOutParam());
    1733                     if (FAILED(rc)) throw rc;
    1734 
    1735                     /* Create a dynamic growing disk image with the given capacity */
    1736                     rc = dstHdVBox->CreateBaseStorage(di.iCapacity / _1M, MediumVariant_Standard, pProgress2.asOutParam());
    1737                     if (FAILED(rc)) throw rc;
    1738 
    1739                     /* Advance to the next operation */
    1740                     stack.pProgress->SetNextOperation(BstrFmt(tr("Creating virtual disk image '%s'"), vsdeHD->strVbox.c_str()),
    1741                                                       vsdeHD->ulSizeMB);     // operation's weight, as set up with the IProgress originally
    1742                 }
    1743                 else
    1744                 {
    1745                     /* Construct the source file path */
    1746                     Utf8StrFmt strSrcFilePath("%s%c%s", strSrcDir.c_str(), RTPATH_DELIMITER, di.strHref.c_str());
    1747                     /* Check if the source file exists */
    1748                     if (!RTPathExists(strSrcFilePath.c_str()))
    1749                         /* This isn't allowed */
    1750                         throw setError(VBOX_E_FILE_ERROR,
    1751                                         tr("Source virtual disk image file '%s' doesn't exist"),
    1752                                             strSrcFilePath.c_str());
    1753 
    1754                     // Clone the disk image (this is necessary cause the id has
    1755                     // to be recreated for the case the same hard disk is
    1756                     // attached already from a previous import)
    1757 
    1758                     // First open the existing disk image
    1759                     rc = mVirtualBox->OpenHardDisk(Bstr(strSrcFilePath),
    1760                                                     AccessMode_ReadOnly,
    1761                                                     false,
    1762                                                     NULL,
    1763                                                     false,
    1764                                                     NULL,
    1765                                                     srcHdVBox.asOutParam());
    1766                     if (FAILED(rc)) throw rc;
    1767                     fSourceHdNeedsClosing = true;
    1768 
    1769                     /* We need the format description of the source disk image */
    1770                     Bstr srcFormat;
    1771                     rc = srcHdVBox->COMGETTER(Format)(srcFormat.asOutParam());
    1772                     if (FAILED(rc)) throw rc;
    1773                     /* Create a new hard disk interface for the destination disk image */
    1774                     rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(vsdeHD->strVbox), dstHdVBox.asOutParam());
    1775                     if (FAILED(rc)) throw rc;
    1776                     /* Clone the source disk image */
    1777                     rc = srcHdVBox->CloneTo(dstHdVBox, MediumVariant_Standard, NULL, pProgress2.asOutParam());
    1778                     if (FAILED(rc)) throw rc;
    1779 
    1780                     /* Advance to the next operation */
    1781                     stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), strSrcFilePath.c_str()),
    1782                                                       vsdeHD->ulSizeMB);     // operation's weight, as set up with the IProgress originally);
    1783                 }
    1784 
    1785                 // now wait for the background disk operation to complete; this throws HRESULTs on error
    1786                 waitForAsyncProgress(stack.pProgress, pProgress2);
    1787 
    1788                 if (fSourceHdNeedsClosing)
    1789                 {
    1790                     rc = srcHdVBox->Close();
    1791                     if (FAILED(rc)) throw rc;
    1792                     fSourceHdNeedsClosing = false;
    1793                 }
    1794 
    1795                 stack.llHardDisksCreated.push_back(dstHdVBox);
     1845                ComPtr<IMedium> pTargetHD;
     1846                importOneDiskImage(di,
     1847                                   vsdeHD->ulSizeMB,
     1848                                   vsdeHD->strVbox,
     1849                                   pTargetHD,
     1850                                   stack);
     1851
    17961852                /* Now use the new uuid to attach the disk image to our new machine */
    17971853                ComPtr<IMachine> sMachine;
     
    17991855                if (FAILED(rc)) throw rc;
    18001856                Bstr hdId;
    1801                 rc = dstHdVBox->COMGETTER(Id)(hdId.asOutParam());
     1857                rc = pTargetHD->COMGETTER(Id)(hdId.asOutParam());
    18021858                if (FAILED(rc)) throw rc;
    18031859
     
    18381894        catch(HRESULT /* aRC */)
    18391895        {
    1840             if (fSourceHdNeedsClosing)
    1841                 srcHdVBox->Close();
    1842 
    18431896            if (stack.fSessionOpen)
    18441897                stack.pSession->Close();
     
    18611914 * @param stack
    18621915 */
    1863 void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis,
     1916void Appliance::importVBoxMachine(const ovf::VirtualSystem &vsysThis,
     1917                                  ComObjPtr<VirtualSystemDescription> &vsdescThis,
    18641918                                  ComPtr<IMachine> &pReturnNewMachine,
    18651919                                  ImportStack &stack)
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r28110 r28162  
    3131class Progress;
    3232class VirtualSystemDescription;
     33struct VirtualSystemDescriptionEntry;
    3334
    3435namespace ovf
     
    3738    struct VirtualSystem;
    3839    class OVFReader;
     40    struct DiskImage;
    3941}
    4042
     
    120122    void addWarning(const char* aWarning, ...);
    121123
    122     void disksWeight(uint32_t &ulTotalMB, uint32_t &cDisks) const;
    123     HRESULT setUpProgressFS(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription);
    124     HRESULT setUpProgressImportS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription);
    125     HRESULT setUpProgressWriteS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription);
     124    void disksWeight();
     125    enum SetUpProgressMode { Regular, ImportS3, WriteS3 };
     126    HRESULT setUpProgress(ComObjPtr<Progress> &pProgress,
     127                          const Bstr &bstrDescription,
     128                          SetUpProgressMode mode);
    126129
    127130    struct LocationInfo;
     
    145148
    146149    HRESULT importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress);
     150    HRESULT manifestVerify(const LocationInfo &locInfo, const ovf::OVFReader &reader);
    147151
    148152    HRESULT importFS(const LocationInfo &locInfo, ComObjPtr<Progress> &aProgress);
     153
    149154    struct ImportStack;
    150     void importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis,
    151                            ComPtr<IMachine> &pNewMachine,
    152                            ImportStack &stack);
     155    void importOneDiskImage(const ovf::DiskImage &di,
     156                            uint32_t ulSizeMB,
     157                            const Utf8Str &strTargetPath,
     158                            ComPtr<IMedium> &pTargetHD,
     159                            ImportStack &stack);
    153160    void importMachineGeneric(const ovf::VirtualSystem &vsysThis,
    154161                              ComObjPtr<VirtualSystemDescription> &vsdescThis,
    155162                              ComPtr<IMachine> &pNewMachine,
    156163                              ImportStack &stack);
     164    void importVBoxMachine(const ovf::VirtualSystem &vsysThis,
     165                           ComObjPtr<VirtualSystemDescription> &vsdescThis,
     166                           ComPtr<IMachine> &pNewMachine,
     167                           ImportStack &stack);
     168
    157169    HRESULT importS3(TaskOVF *pTask);
    158170
  • trunk/src/VBox/Main/include/ApplianceImplPrivate.h

    r27976 r28162  
    8080
    8181    ULONG           ulWeightPerOperation;
     82    ULONG           ulTotalDisksMB;
     83    ULONG           cDisks;
    8284    Utf8Str         strOVFSHA1Digest;
    8385};
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