VirtualBox

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


Ignore:
Timestamp:
Aug 13, 2010 6:40:53 PM (14 years ago)
Author:
vboxsync
Message:

Main/FE/Qt4: add initial OVA support

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

Legend:

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

    r31562 r31676  
    667667    BOOL fCanceled;
    668668    ULONG currentPercent;
     669    ULONG cOp = 0;
    669670    while (SUCCEEDED(pProgressAsync->COMGETTER(Completed(&fCompleted))))
    670671    {
     
    676677            break;
    677678        }
    678 
    679         rc = pProgressAsync->COMGETTER(Percent(&currentPercent));
     679        /* Check if the current operation have changed. It is also possible
     680           that in the meantime more than one async operation was finished. So
     681           we have to loop as long as we reached the same operation count. */
     682        ULONG curOp;
     683        for(;;)
     684        {
     685            rc = pProgressAsync->COMGETTER(Operation(&curOp));
     686            if (FAILED(rc)) throw rc;
     687            if (cOp != curOp)
     688            {
     689                Bstr bstr;
     690                ULONG currentWeight;
     691                rc = pProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));
     692                if (FAILED(rc)) throw rc;
     693                rc = pProgressAsync->COMGETTER(OperationWeight(&currentWeight));
     694                if (FAILED(rc)) throw rc;
     695                rc = pProgressThis->SetNextOperation(bstr, currentWeight);
     696                if (FAILED(rc)) throw rc;
     697                ++cOp;
     698            }else
     699                break;
     700        }
     701
     702        rc = pProgressAsync->COMGETTER(OperationPercent(&currentPercent));
    680703        if (FAILED(rc)) throw rc;
    681         if (!pProgressThis.isNull())
    682             pProgressThis->SetCurrentOperationProgress(currentPercent);
     704        pProgressThis->SetCurrentOperationProgress(currentPercent);
    683705        if (fCompleted)
    684706            break;
     
    745767}
    746768
     769#include <iprt/tar.h>
    747770/**
    748771 * Called from Appliance::importImpl() and Appliance::writeImpl() to set up a
     
    754777 * @return
    755778 */
    756 HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
     779HRESULT Appliance::setUpProgress(const LocationInfo &locInfo,
     780                                 ComObjPtr<Progress> &pProgress,
    757781                                 const Bstr &bstrDescription,
    758782                                 SetUpProgressMode mode)
     
    785809    }
    786810
     811    bool fOVA = locInfo.strPath.endsWith(".ova", Utf8Str::CaseInsensitive);
    787812    switch (mode)
    788813    {
    789814        case ImportFileNoManifest:
    790         break;
    791 
     815        {
     816            if (fOVA)
     817            {
     818                // Another operation for packing
     819                ++cOperations;
     820
     821                // assume that packing the files into the archive has the same weight than creating all files in the ovf exporting step
     822                ulTotalOperationsWeight += m->ulTotalDisksMB;
     823            }
     824            break;
     825        }
    792826        case ImportFileWithManifest:
    793827        case WriteFile:
     828        {
    794829            ++cOperations;          // another one for creating the manifest
    795830
    796             // assume that checking or creating the manifest will take 10% of the time it takes to export the disks
     831            // assume that creating the manifest will take 10% of the time it takes to export the disks
    797832            m->ulWeightForManifestOperation = m->ulTotalDisksMB / 10;
    798833            ulTotalOperationsWeight += m->ulWeightForManifestOperation;
    799         break;
    800 
     834            if (fOVA)
     835            {
     836                // Another operation for packing
     837                ++cOperations;
     838
     839                // assume that packing the files into the archive has the same weight than creating all files in the ovf exporting step
     840                ulTotalOperationsWeight += m->ulTotalDisksMB;
     841            }
     842            break;
     843        }
    801844        case ImportS3:
    802845        {
     
    814857            ULONG ulInitWeight = (ULONG)((double)ulTotalOperationsWeight * 0.1  / 100);  // use 0.1% for init
    815858            ulTotalOperationsWeight += ulInitWeight;
     859            break;
    816860        }
    817         break;
    818 
    819861        case WriteS3:
    820862        {
     
    834876            ULONG ulOVFCreationWeight = (ULONG)((double)ulTotalOperationsWeight * 50.0 / 100.0); /* Use 50% for the creation of the OVF & the disks */
    835877            ulTotalOperationsWeight += ulOVFCreationWeight;
     878            break;
    836879        }
    837         break;
    838880    }
    839881
     
    916958}
    917959
    918 Utf8Str Appliance::manifestFileName(Utf8Str aPath) const
    919 {
     960Utf8Str Appliance::manifestFileName(const Utf8Str& aPath) const
     961{
     962    Utf8Str strTmpPath = aPath;
    920963    /* Get the name part */
    921     char *pszMfName = RTStrDup(RTPathFilename(aPath.c_str()));
     964    char *pszMfName = RTStrDup(RTPathFilename(strTmpPath.c_str()));
    922965    /* Strip any extensions */
    923966    RTPathStripExt(pszMfName);
    924967    /* Path without the filename */
    925     aPath.stripFilename();
     968    strTmpPath.stripFilename();
    926969    /* Format the manifest path */
    927     Utf8StrFmt strMfFile("%s/%s.mf", aPath.c_str(), pszMfName);
     970    Utf8StrFmt strMfFile("%s/%s.mf", strTmpPath.c_str(), pszMfName);
    928971    RTStrFree(pszMfName);
    929972    return strMfFile;
     
    9731016        case TaskOVF::Read:
    9741017            if (task->locInfo.storageType == VFSType_File)
    975                 taskrc = pAppliance->readFS(task->locInfo);
     1018                taskrc = pAppliance->readFS(task->locInfo, task->pProgress);
    9761019            else if (task->locInfo.storageType == VFSType_S3)
    9771020                taskrc = pAppliance->readS3(task.get());
     
    9801023        case TaskOVF::Import:
    9811024            if (task->locInfo.storageType == VFSType_File)
    982                 taskrc = pAppliance->importFS(task->locInfo, task->pProgress);
     1025                taskrc = pAppliance->importFS(task.get());
    9831026            else if (task->locInfo.storageType == VFSType_S3)
    9841027                taskrc = pAppliance->importS3(task.get());
     
    9871030        case TaskOVF::Write:
    9881031            if (task->locInfo.storageType == VFSType_File)
    989                 taskrc = pAppliance->writeFS(task->locInfo, task->enFormat, task->pProgress);
     1032                taskrc = pAppliance->writeFS(task.get());
    9901033            else if (task->locInfo.storageType == VFSType_S3)
    9911034                taskrc = pAppliance->writeS3(task.get());
  • trunk/src/VBox/Main/ApplianceImplExport.cpp

    r31615 r31676  
    2222#include <iprt/s3.h>
    2323#include <iprt/manifest.h>
     24#include <iprt/tar.h>
     25#include <iprt/stream.h>
    2426
    2527#include <VBox/version.h>
     
    566568    // see if we can handle this file; for now we insist it has an ".ovf" extension
    567569    Utf8Str strPath = path;
    568     if (!strPath.endsWith(".ovf", Utf8Str::CaseInsensitive))
     570    if (!(   strPath.endsWith(".ovf", Utf8Str::CaseInsensitive)
     571          || strPath.endsWith(".ova", Utf8Str::CaseInsensitive)))
    569572        return setError(VBOX_E_FILE_ERROR,
    570                         tr("Appliance file must have .ovf extension"));
     573                        tr("Appliance file must have .ovf or .ova extension"));
    571574
    572575    Utf8Str strFormat(format);
     
    613616 *
    614617 * 1) from the public Appliance::Write().
    615  * 2) from Appliance::writeS3(), which got called from a previous instance of Appliance::taskThreadWriteOVF().
     618 *
     619 * 2) in a second worker thread; in that case, Appliance::Write() called Appliance::writeImpl(), which
     620 *    called Appliance::writeFSOVA(), which called Appliance::writeImpl(), which then called this again.
     621 *
     622 * 3) from Appliance::writeS3(), which got called from a previous instance of Appliance::taskThreadWriteOVF().
    616623 *
    617624 * @param aFormat
     
    625632    try
    626633    {
    627         rc = setUpProgress(aProgress,
     634        rc = setUpProgress(aLocInfo,
     635                           aProgress,
    628636                           BstrFmt(tr("Export appliance '%s'"), aLocInfo.strPath.c_str()),
    629637                           (aLocInfo.storageType == VFSType_File) ? WriteFile : WriteS3);
     
    13101318
    13111319/**
    1312  * Actual worker code for writing out OVF to disk. This is called from Appliance::taskThreadWriteOVF()
    1313  * and therefore runs on the OVF write worker thread. This runs in two contexts:
     1320 * Actual worker code for writing out OVF/OVA to disk. This is called from Appliance::taskThreadWriteOVF()
     1321 * and therefore runs on the OVF/OVA write worker thread. This runs in two contexts:
    13141322 *
    13151323 * 1) in a first worker thread; in that case, Appliance::Write() called Appliance::writeImpl();
     
    13231331 * @return
    13241332 */
    1325 HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat, ComObjPtr<Progress> &pProgress)
     1333HRESULT Appliance::writeFS(TaskOVF *pTask)
    13261334{
     1335    if (pTask->locInfo.strPath.endsWith(".ovf", Utf8Str::CaseInsensitive))
     1336        return writeFSOVF(pTask);
     1337    else
     1338        return writeFSOVA(pTask);
     1339}
     1340
     1341HRESULT Appliance::writeFSOVF(TaskOVF *pTask)
     1342{
     1343    LogFlowFuncEnter();
    13271344    LogFlowFunc(("ENTER appliance %p\n", this));
    13281345
     
    13391356        xml::ElementNode *pelmRoot = doc.createRootElement("Envelope");
    13401357
    1341         pelmRoot->setAttribute("ovf:version", (enFormat == OVF_1_0) ? "1.0" : "0.9");
     1358        pelmRoot->setAttribute("ovf:version", (pTask->enFormat == OVF_1_0) ? "1.0" : "0.9");
    13421359        pelmRoot->setAttribute("xml:lang", "en-US");
    13431360
    1344         Utf8Str strNamespace = (enFormat == OVF_0_9)
     1361        Utf8Str strNamespace = (pTask->enFormat == OVF_0_9)
    13451362            ? "http://www.vmware.com/schema/ovf/1/envelope"     // 0.9
    13461363            : "http://schemas.dmtf.org/ovf/envelope/1";         // 1.0
     
    13641381            </DiskSection> */
    13651382        xml::ElementNode *pelmDiskSection;
    1366         if (enFormat == OVF_0_9)
     1383        if (pTask->enFormat == OVF_0_9)
    13671384        {
    13681385            // <Section xsi:type="ovf:DiskSection_Type">
     
    13891406            </NetworkSection> */
    13901407        xml::ElementNode *pelmNetworkSection;
    1391         if (enFormat == OVF_0_9)
     1408        if (pTask->enFormat == OVF_0_9)
    13921409        {
    13931410            // <Section xsi:type="ovf:NetworkSection_Type">
     
    14151432        if (m->virtualSystemDescriptions.size() > 1)
    14161433        {
    1417             if (enFormat == OVF_0_9)
     1434            if (pTask->enFormat == OVF_0_9)
    14181435                throw setError(VBOX_E_FILE_ERROR,
    14191436                               tr("Cannot export more than one virtual system with OVF 0.9, use OVF 1.0"));
     
    14391456                                        &llElementsWithUuidAttributes,
    14401457                                        vsdescThis,
    1441                                         enFormat,
     1458                                        pTask->enFormat,
    14421459                                        stack);         // disks and networks stack
    14431460        }
     
    14941511            const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf;
    14951512            // target path needs to be composed from where the output OVF is
    1496             Utf8Str strTargetFilePath(locInfo.strPath);
     1513            Utf8Str strTargetFilePath(pTask->locInfo.strPath);
    14971514            strTargetFilePath.stripFilename();
    14981515            strTargetFilePath.append("/");
     
    15181535
    15191536                // advance to the next operation
    1520                 pProgress->SetNextOperation(BstrFmt(tr("Exporting to disk image '%s'"), strTargetFilePath.c_str()),
    1521                                             pDiskEntry->ulSizeMB);     // operation's weight, as set up with the IProgress originally);
     1537                pTask->pProgress->SetNextOperation(BstrFmt(tr("Exporting to disk image '%s'"), RTPathFilename(strTargetFilePath.c_str())),
     1538                                                   pDiskEntry->ulSizeMB);     // operation's weight, as set up with the IProgress originally);
    15221539
    15231540                // now wait for the background disk operation to complete; this throws HRESULTs on error
    1524                 waitForAsyncProgress(pProgress, pProgress2);
     1541                waitForAsyncProgress(pTask->pProgress, pProgress2);
    15251542            }
    15261543            catch (HRESULT rc3)
     
    15681585            pelmDisk->setAttribute("ovf:fileRef", strFileRef);
    15691586            pelmDisk->setAttribute("ovf:format",
    1570                     (enFormat == OVF_0_9)
     1587                    (pTask->enFormat == OVF_0_9)
    15711588                        ?  "http://www.vmware.com/specifications/vmdk.html#sparse"      // must be sparse or ovftool chokes
    15721589                        :  "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized"
     
    15931610        // now go write the XML
    15941611        xml::XmlFileWriter writer(doc);
    1595         writer.write(locInfo.strPath.c_str(), false /*fSafe*/);
     1612        writer.write(pTask->locInfo.strPath.c_str(), false /*fSafe*/);
    15961613
    15971614        // Create & write the manifest file
    1598         Utf8Str strMfFile = manifestFileName(locInfo.strPath.c_str());
     1615        Utf8Str strMfFile = manifestFileName(pTask->locInfo.strPath.c_str());
    15991616        const char *pcszManifestFileOnly = RTPathFilename(strMfFile.c_str());
    1600         pProgress->SetNextOperation(BstrFmt(tr("Creating manifest file '%s'"), pcszManifestFileOnly),
    1601                                     m->ulWeightForManifestOperation);     // operation's weight, as set up with the IProgress originally);
     1617        pTask->pProgress->SetNextOperation(BstrFmt(tr("Creating manifest file '%s'"), pcszManifestFileOnly),
     1618                                           m->ulWeightForManifestOperation);     // operation's weight, as set up with the IProgress originally);
    16021619
    16031620        const char** ppManifestFiles = (const char**)RTMemAlloc(sizeof(char*)*diskList.size() + 1);
    1604         ppManifestFiles[0] = locInfo.strPath.c_str();
     1621        ppManifestFiles[0] = pTask->locInfo.strPath.c_str();
    16051622        list<Utf8Str>::const_iterator it1;
    16061623        size_t i = 1;
     
    16361653}
    16371654
    1638 /**
    1639  * Worker code for writing out OVF to the cloud. This is called from Appliance::taskThreadWriteOVF()
    1640  * in S3 mode and therefore runs on the OVF write worker thread. This then starts a second worker
    1641  * thread to create temporary files (see Appliance::writeFS()).
    1642  *
    1643  * @param pTask
    1644  * @return
    1645  */
    1646 HRESULT Appliance::writeS3(TaskOVF *pTask)
     1655HRESULT Appliance::writeFSOVA(TaskOVF *pTask)
    16471656{
    16481657    LogFlowFuncEnter();
     
    16571666
    16581667    int vrc = VINF_SUCCESS;
    1659     RTS3 hS3 = NIL_RTS3;
     1668
    16601669    char szOSTmpDir[RTPATH_MAX];
    16611670    RTPathTemp(szOSTmpDir, sizeof(szOSTmpDir));
     
    16631672    char *pszTmpDir;
    16641673    RTStrAPrintf(&pszTmpDir, "%s"RTPATH_SLASH_STR"vbox-ovf-XXXXXX", szOSTmpDir);
    1665     list< pair<Utf8Str, ULONG> > filesList;
    1666 
    1667     // todo:
    1668     // - usable error codes
    1669     // - seems snapshot filenames are problematic {uuid}.vdi
     1674    list<Utf8Str> filesList;
     1675    const char** paFiles = 0;
     1676
    16701677    try
    16711678    {
    1672         /* Extract the bucket */
     1679        /* Extract the path */
    16731680        Utf8Str tmpPath = pTask->locInfo.strPath;
    1674         Utf8Str bucket;
    1675         parseBucket(tmpPath, bucket);
     1681        /* Remove the ova extension */
     1682        tmpPath.stripExt();
     1683        tmpPath += ".ovf";
    16761684
    16771685        /* We need a temporary directory which we can put the OVF file & all
     
    16801688        if (RT_FAILURE(vrc))
    16811689            throw setError(VBOX_E_FILE_ERROR,
    1682                            tr("Cannot create temporary directory '%s'"), pszTmpDir);
     1690                           tr("Cannot create temporary directory '%s' (%Rrc)"), pszTmpDir, vrc);
    16831691
    16841692        /* The temporary name of the target OVF file */
     
    17061714        if (RT_FAILURE(vrc))
    17071715            throw setError(VBOX_E_FILE_ERROR,
    1708                            tr("Cannot find source file '%s'"), strTmpOvf.c_str());
     1716                           tr("Cannot find source file '%s' (%Rrc)"), strTmpOvf.c_str(), vrc);
    17091717        /* Add the OVF file */
    1710         filesList.push_back(pair<Utf8Str, ULONG>(strTmpOvf, m->ulWeightForXmlOperation)); /* Use 1% of the total for the OVF file upload */
     1718        filesList.push_back(strTmpOvf); /* Use 1% of the total for the OVF file upload */
    17111719        Utf8Str strMfFile = manifestFileName(strTmpOvf);
    1712         filesList.push_back(pair<Utf8Str, ULONG>(strMfFile , m->ulWeightForXmlOperation)); /* Use 1% of the total for the manifest file upload */
    1713 
     1720        filesList.push_back(strMfFile); /* Use 1% of the total for the manifest file upload */
     1721
     1722        ULONG ulWeight = 2 * m->ulWeightForXmlOperation;
    17141723        /* Now add every disks of every virtual system */
    17151724        list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
     
    17341743                if (RT_FAILURE(vrc))
    17351744                    throw setError(VBOX_E_FILE_ERROR,
    1736                                    tr("Cannot find source file '%s'"), strTargetFilePath.c_str());
     1745                                   tr("Cannot find source file '%s' (%Rrc)"), strTargetFilePath.c_str(), vrc);
     1746                filesList.push_back(strTargetFilePath);
     1747                ulWeight += (*itH)->ulSizeMB;
     1748            }
     1749        }
     1750        paFiles = (const char**)RTMemAlloc(sizeof(char*) * filesList.size());
     1751        int i = 0;
     1752        for (list<Utf8Str>::const_iterator it1 = filesList.begin(); it1 != filesList.end(); ++it1, ++i)
     1753            paFiles[i] = (*it1).c_str();
     1754        pTask->pProgress->SetNextOperation(BstrFmt(tr("Packing into '%s'"), RTPathFilename(pTask->locInfo.strPath.c_str())), ulWeight);
     1755        /* Create the tar file out of our file list. */
     1756        vrc = RTTarCreate(pTask->locInfo.strPath.c_str(), paFiles, filesList.size(), pTask->updateProgress, &pTask);
     1757        if (RT_FAILURE(vrc))
     1758            throw setError(VBOX_E_FILE_ERROR,
     1759                           tr("Cannot create OVA file '%s' (%Rrc)"), pTask->locInfo.strPath.c_str(), vrc);
     1760    }
     1761    catch(HRESULT aRC)
     1762    {
     1763        rc = aRC;
     1764    }
     1765
     1766    /* Delete the temporary files list */
     1767    if (paFiles)
     1768        RTMemFree(paFiles);
     1769    /* Delete all files which where temporary created */
     1770    for (list<Utf8Str>::const_iterator it1 = filesList.begin(); it1 != filesList.end(); ++it1)
     1771    {
     1772        const char *pszFilePath = (*it1).c_str();
     1773        if (RTPathExists(pszFilePath))
     1774        {
     1775            vrc = RTFileDelete(pszFilePath);
     1776            if (RT_FAILURE(vrc))
     1777                rc = setError(VBOX_E_FILE_ERROR,
     1778                              tr("Cannot delete file '%s' (%Rrc)"), pszFilePath, vrc);
     1779        }
     1780    }
     1781    /* Delete the temporary directory */
     1782    if (RTPathExists(pszTmpDir))
     1783    {
     1784        vrc = RTDirRemove(pszTmpDir);
     1785        if (RT_FAILURE(vrc))
     1786            rc = setError(VBOX_E_FILE_ERROR,
     1787                          tr("Cannot delete temporary directory '%s' (%Rrc)"), pszTmpDir, vrc);
     1788    }
     1789    if (pszTmpDir)
     1790        RTStrFree(pszTmpDir);
     1791
     1792    LogFlowFunc(("rc=%Rhrc\n", rc));
     1793    LogFlowFuncLeave();
     1794
     1795    return rc;
     1796}
     1797
     1798/**
     1799 * Worker code for writing out OVF to the cloud. This is called from Appliance::taskThreadWriteOVF()
     1800 * in S3 mode and therefore runs on the OVF write worker thread. This then starts a second worker
     1801 * thread to create temporary files (see Appliance::writeFS()).
     1802 *
     1803 * @param pTask
     1804 * @return
     1805 */
     1806HRESULT Appliance::writeS3(TaskOVF *pTask)
     1807{
     1808    LogFlowFuncEnter();
     1809    LogFlowFunc(("Appliance %p\n", this));
     1810
     1811    AutoCaller autoCaller(this);
     1812    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     1813
     1814    HRESULT rc = S_OK;
     1815
     1816    AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
     1817
     1818    int vrc = VINF_SUCCESS;
     1819    RTS3 hS3 = NIL_RTS3;
     1820    char szOSTmpDir[RTPATH_MAX];
     1821    RTPathTemp(szOSTmpDir, sizeof(szOSTmpDir));
     1822    /* The template for the temporary directory created below */
     1823    char *pszTmpDir;
     1824    RTStrAPrintf(&pszTmpDir, "%s"RTPATH_SLASH_STR"vbox-ovf-XXXXXX", szOSTmpDir);
     1825    list< pair<Utf8Str, ULONG> > filesList;
     1826
     1827    // todo:
     1828    // - usable error codes
     1829    // - seems snapshot filenames are problematic {uuid}.vdi
     1830    try
     1831    {
     1832        /* Extract the bucket */
     1833        Utf8Str tmpPath = pTask->locInfo.strPath;
     1834        Utf8Str bucket;
     1835        parseBucket(tmpPath, bucket);
     1836
     1837        /* We need a temporary directory which we can put the OVF file & all
     1838         * disk images in */
     1839        vrc = RTDirCreateTemp(pszTmpDir);
     1840        if (RT_FAILURE(vrc))
     1841            throw setError(VBOX_E_FILE_ERROR,
     1842                           tr("Cannot create temporary directory '%s' (%Rrc)"), pszTmpDir, vrc);
     1843
     1844        /* The temporary name of the target OVF file */
     1845        Utf8StrFmt strTmpOvf("%s/%s", pszTmpDir, RTPathFilename(tmpPath.c_str()));
     1846
     1847        /* Prepare the temporary writing of the OVF */
     1848        ComObjPtr<Progress> progress;
     1849        /* Create a temporary file based location info for the sub task */
     1850        LocationInfo li;
     1851        li.strPath = strTmpOvf;
     1852        rc = writeImpl(pTask->enFormat, li, progress);
     1853        if (FAILED(rc)) throw rc;
     1854
     1855        /* Unlock the appliance for the writing thread */
     1856        appLock.release();
     1857        /* Wait until the writing is done, but report the progress back to the
     1858           caller */
     1859        ComPtr<IProgress> progressInt(progress);
     1860        waitForAsyncProgress(pTask->pProgress, progressInt); /* Any errors will be thrown */
     1861
     1862        /* Again lock the appliance for the next steps */
     1863        appLock.acquire();
     1864
     1865        vrc = RTPathExists(strTmpOvf.c_str()); /* Paranoid check */
     1866        if (RT_FAILURE(vrc))
     1867            throw setError(VBOX_E_FILE_ERROR,
     1868                           tr("Cannot find source file '%s' (%Rrc)"), strTmpOvf.c_str(), vrc);
     1869        /* Add the OVF file */
     1870        filesList.push_back(pair<Utf8Str, ULONG>(strTmpOvf, m->ulWeightForXmlOperation)); /* Use 1% of the total for the OVF file upload */
     1871        Utf8Str strMfFile = manifestFileName(strTmpOvf);
     1872        filesList.push_back(pair<Utf8Str, ULONG>(strMfFile , m->ulWeightForXmlOperation)); /* Use 1% of the total for the manifest file upload */
     1873
     1874        /* Now add every disks of every virtual system */
     1875        list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
     1876        for (it = m->virtualSystemDescriptions.begin();
     1877             it != m->virtualSystemDescriptions.end();
     1878             ++it)
     1879        {
     1880            ComObjPtr<VirtualSystemDescription> vsdescThis = (*it);
     1881            std::list<VirtualSystemDescriptionEntry*> avsdeHDs = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskImage);
     1882            std::list<VirtualSystemDescriptionEntry*>::const_iterator itH;
     1883            for (itH = avsdeHDs.begin();
     1884                 itH != avsdeHDs.end();
     1885                 ++itH)
     1886            {
     1887                const Utf8Str &strTargetFileNameOnly = (*itH)->strOvf;
     1888                /* Target path needs to be composed from where the output OVF is */
     1889                Utf8Str strTargetFilePath(strTmpOvf);
     1890                strTargetFilePath.stripFilename();
     1891                strTargetFilePath.append("/");
     1892                strTargetFilePath.append(strTargetFileNameOnly);
     1893                vrc = RTPathExists(strTargetFilePath.c_str()); /* Paranoid check */
     1894                if (RT_FAILURE(vrc))
     1895                    throw setError(VBOX_E_FILE_ERROR,
     1896                                   tr("Cannot find source file '%s' (%Rrc)"), strTargetFilePath.c_str(), vrc);
    17371897                filesList.push_back(pair<Utf8Str, ULONG>(strTargetFilePath, (*itH)->ulSizeMB));
    17381898            }
  • trunk/src/VBox/Main/ApplianceImplImport.cpp

    r31615 r31676  
    2323#include <iprt/sha.h>
    2424#include <iprt/manifest.h>
     25#include <iprt/tar.h>
     26#include <iprt/stream.h>
    2527
    2628#include <VBox/com/array.h>
     
    7779    // see if we can handle this file; for now we insist it has an ".ovf" extension
    7880    Utf8Str strPath (path);
    79     if (!strPath.endsWith(".ovf", Utf8Str::CaseInsensitive))
     81    if (!(   strPath.endsWith(".ovf", Utf8Str::CaseInsensitive)
     82          || strPath.endsWith(".ova", Utf8Str::CaseInsensitive)))
    8083        return setError(VBOX_E_FILE_ERROR,
    8184                        tr("Appliance file must have .ovf extension"));
     
    599602 * This will then open the OVF with ovfreader.cpp.
    600603 *
    601  * This is in a separate private method because it is used from two locations:
     604 * This is in a separate private method because it is used from three locations:
    602605 *
    603606 * 1) from the public Appliance::Read().
    604  * 2) from Appliance::readS3(), which got called from a previous instance of Appliance::taskThreadImportOrExport().
     607 *
     608 * 2) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which
     609 *    called Appliance::readFSOVA(), which called Appliance::importImpl(), which then called this again.
     610 *
     611 * 3) from Appliance::readS3(), which got called from a previous instance of Appliance::taskThreadImportOrExport().
    605612 *
    606613 * @param aLocInfo
     
    658665 * @return
    659666 */
    660 HRESULT Appliance::readFS(const LocationInfo &locInfo)
     667HRESULT Appliance::readFS(const LocationInfo &locInfo, ComObjPtr<Progress> &pProgress)
     668{
     669    if (locInfo.strPath.endsWith(".ovf", Utf8Str::CaseInsensitive))
     670        return readFSOVF(locInfo, pProgress);
     671    else
     672        return readFSOVA(locInfo, pProgress);
     673}
     674
     675HRESULT Appliance::readFSOVF(const LocationInfo &locInfo, ComObjPtr<Progress> & /* pProgress */)
    661676{
    662677    LogFlowFuncEnter();
     
    693708        rc = aRC;
    694709    }
     710
     711    LogFlowFunc(("rc=%Rhrc\n", rc));
     712    LogFlowFuncLeave();
     713
     714    return rc;
     715}
     716
     717HRESULT Appliance::readFSOVA(const LocationInfo &locInfo, ComObjPtr<Progress> &pProgress)
     718{
     719    LogFlowFuncEnter();
     720    LogFlowFunc(("Appliance %p\n", this));
     721
     722    AutoCaller autoCaller(this);
     723    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     724
     725    AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
     726
     727    HRESULT rc = S_OK;
     728    int vrc = VINF_SUCCESS;
     729    char szOSTmpDir[RTPATH_MAX];
     730    RTPathTemp(szOSTmpDir, sizeof(szOSTmpDir));
     731    /* The template for the temporary directory created below */
     732    char *pszTmpDir;
     733    RTStrAPrintf(&pszTmpDir, "%s"RTPATH_SLASH_STR"vbox-ovf-XXXXXX", szOSTmpDir);
     734    list< pair<Utf8Str, ULONG> > filesList;
     735    Utf8Str strTmpOvf;
     736
     737    try
     738    {
     739        /* Extract the path */
     740        Utf8Str tmpPath = locInfo.strPath;
     741        /* Remove the ova extension */
     742        tmpPath.stripExt();
     743        tmpPath += ".ovf";
     744
     745        /* We need a temporary directory which we can put the OVF file & all
     746         * disk images in */
     747        vrc = RTDirCreateTemp(pszTmpDir);
     748        if (RT_FAILURE(vrc))
     749            DebugBreakThrow(setError(VBOX_E_FILE_ERROR,
     750                           tr("Cannot create temporary directory '%s' (%Rrc)"), pszTmpDir, vrc));
     751
     752        /* The temporary name of the target OVF file */
     753        strTmpOvf = Utf8StrFmt("%s/%s", pszTmpDir, RTPathFilename(tmpPath.c_str()));
     754
     755        /* Next we have to download the OVF */
     756        char *papszFile = RTPathFilename(strTmpOvf.c_str());
     757        vrc = RTTarExtractFiles(locInfo.strPath.c_str(), pszTmpDir, &papszFile, 1, 0, 0);
     758        if (RT_FAILURE(vrc))
     759        {
     760            if (vrc == VERR_FILE_NOT_FOUND)
     761                DebugBreakThrow(setError(VBOX_E_IPRT_ERROR,
     762                                         tr("Can't find ovf file '%s' in archive '%s' (%Rrc)"), papszFile, locInfo.strPath.c_str(), vrc));
     763            else
     764                DebugBreakThrow(setError(VBOX_E_IPRT_ERROR,
     765                                         tr("Can't unpack the archive file '%s' (%Rrc)"), locInfo.strPath.c_str(), vrc));
     766        }
     767
     768        // todo: check this out
     769//        pTask->pProgress->SetNextOperation(Bstr(tr("Reading")), 1);
     770
     771        /* Prepare the temporary reading of the OVF */
     772        ComObjPtr<Progress> progress;
     773        LocationInfo li;
     774        li.strPath = strTmpOvf;
     775        /* Start the reading from the fs */
     776        rc = readImpl(li, progress);
     777        if (FAILED(rc)) DebugBreakThrow(rc);
     778
     779        /* Unlock the appliance for the reading thread */
     780        appLock.release();
     781        /* Wait until the reading is done, but report the progress back to the
     782           caller */
     783        ComPtr<IProgress> progressInt(progress);
     784        waitForAsyncProgress(pProgress, progressInt); /* Any errors will be thrown */
     785
     786        /* Again lock the appliance for the next steps */
     787        appLock.acquire();
     788    }
     789    catch(HRESULT aRC)
     790    {
     791        rc = aRC;
     792    }
     793    /* Delete all files which where temporary created */
     794    if (RTPathExists(strTmpOvf.c_str()))
     795    {
     796        vrc = RTFileDelete(strTmpOvf.c_str());
     797        if (RT_FAILURE(vrc))
     798            rc = setError(VBOX_E_FILE_ERROR,
     799                          tr("Cannot delete file '%s' (%Rrc)"), strTmpOvf.c_str(), vrc);
     800    }
     801    /* Delete the temporary directory */
     802    if (RTPathExists(pszTmpDir))
     803    {
     804        vrc = RTDirRemove(pszTmpDir);
     805        if (RT_FAILURE(vrc))
     806            rc = setError(VBOX_E_FILE_ERROR,
     807                          tr("Cannot delete temporary directory '%s' (%Rrc)"), pszTmpDir, vrc);
     808    }
     809    if (pszTmpDir)
     810        RTStrFree(pszTmpDir);
    695811
    696812    LogFlowFunc(("rc=%Rhrc\n", rc));
     
    9391055 * @return
    9401056 */
    941 HRESULT Appliance::importImpl(const LocationInfo &aLocInfo,
    942                               ComObjPtr<Progress> &aProgress)
     1057HRESULT Appliance::importImpl(const LocationInfo &locInfo,
     1058                              ComObjPtr<Progress> &progress)
    9431059{
    9441060    HRESULT rc = S_OK;
    9451061
    9461062    SetUpProgressMode mode;
    947     m->strManifestFile.setNull();
    948     if (aLocInfo.storageType == VFSType_File)
    949     {
    950         Utf8Str strMfFile = manifestFileName(aLocInfo.strPath);
    951         if (RTPathExists(strMfFile.c_str()))
    952         {
    953             m->strManifestFile = strMfFile;
    954             mode = ImportFileWithManifest;
     1063    if (locInfo.storageType == VFSType_File)
     1064    {
     1065        mode = ImportFileNoManifest;
     1066        Utf8Str strMfFile = manifestFileName(locInfo.strPath);
     1067        if (!locInfo.strPath.endsWith(".ova", Utf8Str::CaseInsensitive))
     1068        {
     1069            if (RTPathExists(strMfFile.c_str()))
     1070                mode = ImportFileWithManifest;
    9551071        }
    9561072        else
    957             mode = ImportFileNoManifest;
     1073        {
     1074            if (RTTarQueryFileExists(locInfo.strPath.c_str(), RTPathFilename(strMfFile.c_str())) == VINF_SUCCESS)
     1075                mode = ImportFileWithManifest;
     1076        }
    9581077    }
    9591078    else
    9601079         mode = ImportS3;
    9611080
    962     rc = setUpProgress(aProgress,
    963                        BstrFmt(tr("Importing appliance '%s'"), aLocInfo.strPath.c_str()),
     1081    rc = setUpProgress(locInfo,
     1082                       progress,
     1083                       BstrFmt(tr("Importing appliance '%s'"), locInfo.strPath.c_str()),
    9641084                       mode);
    9651085    if (FAILED(rc)) DebugBreakThrow(rc);
    9661086
    9671087    /* Initialize our worker task */
    968     std::auto_ptr<TaskOVF> task(new TaskOVF(this, TaskOVF::Import, aLocInfo, aProgress));
     1088    std::auto_ptr<TaskOVF> task(new TaskOVF(this, TaskOVF::Import, locInfo, progress));
    9691089
    9701090    rc = task->startThread();
     
    9931113    HRESULT rc = S_OK;
    9941114
    995     if (!m->strManifestFile.isEmpty())
    996     {
    997         const char *pcszManifestFileOnly = RTPathFilename(m->strManifestFile.c_str());
     1115    Utf8Str strManifestFile = manifestFileName(locInfo.strPath);
     1116    if (!strManifestFile.isEmpty())
     1117    {
     1118        const char *pcszManifestFileOnly = RTPathFilename(strManifestFile.c_str());
    9981119        pProgress->SetNextOperation(BstrFmt(tr("Verifying manifest file '%s'"), pcszManifestFileOnly),
    9991120                                    m->ulWeightForManifestOperation);     // operation's weight, as set up with the IProgress originally
     
    10431164        // this call can take a very long time
    10441165        size_t cIndexOnError;
    1045         vrc = RTManifestVerify(m->strManifestFile.c_str(),
     1166        vrc = RTManifestVerify(strManifestFile.c_str(),
    10461167                               pTestList,
    10471168                               filesList.size() + 1,
     
    10751196 * VirtualSystemScription instances created by Appliance::Interpret().
    10761197 *
    1077  * This runs in two contexts:
     1198 * This runs in three contexts:
    10781199 *
    10791200 * 1) in a first worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl();
    10801201 *
    10811202 * 2) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which
    1082  *    called Appliance::importS3(), which called Appliance::importImpl(), which then called this.
     1203 *    called Appliance::importFSOVA(), which called Appliance::importImpl(), which then called this again.
     1204 *
     1205 * 3) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which
     1206 *    called Appliance::importS3(), which called Appliance::importImpl(), which then called this again.
    10831207 *
    10841208 * @param pTask
    10851209 * @return
    10861210 */
    1087 HRESULT Appliance::importFS(const LocationInfo &locInfo,
    1088                             ComObjPtr<Progress> &pProgress)
     1211HRESULT Appliance::importFS(TaskOVF *pTask)
     1212{
     1213    if (!Utf8Str(RTPathExt(pTask->locInfo.strPath.c_str())).compare(".ovf", Utf8Str::CaseInsensitive))
     1214        return importFSOVF(pTask);
     1215    else
     1216        return importFSOVA(pTask);
     1217}
     1218
     1219HRESULT Appliance::importFSOVF(TaskOVF *pTask)
    10891220{
    10901221    LogFlowFuncEnter();
     
    10941225    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    10951226
    1096     Assert(!pProgress.isNull());
     1227    Assert(!pTask->pProgress.isNull());
    10971228
    10981229    // Change the appliance state so we can safely leave the lock while doing time-consuming
     
    11121243
    11131244    // rollback for errors:
    1114     ImportStack stack(locInfo, reader.m_mapDisks, pProgress);
     1245    ImportStack stack(pTask->locInfo, reader.m_mapDisks, pTask->pProgress);
    11151246
    11161247    // clear the list of imported machines, if any
     
    11201251    {
    11211252        // if a manifest file exists, verify the content; we then need all files which are referenced by the OVF & the OVF itself
    1122         rc = manifestVerify(locInfo, reader, pProgress);
     1253        rc = manifestVerify(pTask->locInfo, reader, pTask->pProgress);
    11231254        if (FAILED(rc)) DebugBreakThrow(rc);
    11241255
     
    12551386}
    12561387
     1388HRESULT Appliance::importFSOVA(TaskOVF *pTask)
     1389{
     1390    LogFlowFuncEnter();
     1391    LogFlowFunc(("Appliance %p\n", this));
     1392
     1393    AutoCaller autoCaller(this);
     1394    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     1395
     1396    AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
     1397
     1398    int vrc = VINF_SUCCESS;
     1399    char szOSTmpDir[RTPATH_MAX];
     1400    RTPathTemp(szOSTmpDir, sizeof(szOSTmpDir));
     1401    /* The template for the temporary directory created below */
     1402    char *pszTmpDir;
     1403    RTStrAPrintf(&pszTmpDir, "%s"RTPATH_SLASH_STR"vbox-ovf-XXXXXX", szOSTmpDir);
     1404    list< pair<Utf8Str, ULONG> > filesList;
     1405    const char** paFiles = 0;
     1406
     1407    HRESULT rc = S_OK;
     1408    try
     1409    {
     1410        /* Extract the path */
     1411        Utf8Str tmpPath = pTask->locInfo.strPath;
     1412        /* Remove the ova extension */
     1413        tmpPath.stripExt();
     1414        tmpPath += ".ovf";
     1415
     1416        /* We need a temporary directory which we can put the all disk images
     1417         * in */
     1418        vrc = RTDirCreateTemp(pszTmpDir);
     1419        if (RT_FAILURE(vrc))
     1420            DebugBreakThrow(setError(VBOX_E_FILE_ERROR,
     1421                                     tr("Cannot create temporary directory '%s' (%Rrc)"), pszTmpDir, vrc));
     1422
     1423        /* Provide a OVF file (haven't to exist) so the import routine can
     1424         * figure out where the disk images/manifest file are located. */
     1425        Utf8StrFmt strTmpOvf("%s/%s", pszTmpDir, RTPathFilename(tmpPath.c_str()));
     1426        /* Add the manifest file to the list of files to extract, but only if
     1427           one is in the archive. */
     1428        Utf8Str strManifestFile = manifestFileName(strTmpOvf);
     1429        vrc = RTTarQueryFileExists(pTask->locInfo.strPath.c_str(), RTPathFilename(strManifestFile.c_str()));
     1430        if (RT_SUCCESS(vrc))
     1431            filesList.push_back(pair<Utf8Str, ULONG>(strManifestFile.c_str(), 1));
     1432
     1433        ULONG ulWeight = m->ulWeightForXmlOperation;
     1434        /* Add every disks of every virtual system to an internal list */
     1435        list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
     1436        for (it = m->virtualSystemDescriptions.begin();
     1437             it != m->virtualSystemDescriptions.end();
     1438             ++it)
     1439        {
     1440            ComObjPtr<VirtualSystemDescription> vsdescThis = (*it);
     1441            std::list<VirtualSystemDescriptionEntry*> avsdeHDs = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskImage);
     1442            std::list<VirtualSystemDescriptionEntry*>::const_iterator itH;
     1443            for (itH = avsdeHDs.begin();
     1444                 itH != avsdeHDs.end();
     1445                 ++itH)
     1446            {
     1447                const Utf8Str &strTargetFile = (*itH)->strOvf;
     1448                if (!strTargetFile.isEmpty())
     1449                {
     1450                    /* The temporary name of the target disk file */
     1451                    Utf8StrFmt strTmpDisk("%s/%s", pszTmpDir, RTPathFilename(strTargetFile.c_str()));
     1452                    filesList.push_back(pair<Utf8Str, ULONG>(strTmpDisk, (*itH)->ulSizeMB));
     1453                    ulWeight += (*itH)->ulSizeMB;
     1454                }
     1455            }
     1456        }
     1457
     1458        /* Download all files */
     1459        paFiles = (const char**)RTMemAlloc(sizeof(char*) * filesList.size());
     1460        int i = 0;
     1461        for (list< pair<Utf8Str, ULONG> >::const_iterator it1 = filesList.begin(); it1 != filesList.end(); ++it1, ++i)
     1462            paFiles[i] = RTPathFilename((*it1).first.c_str());
     1463        if (!pTask->pProgress.isNull())
     1464            pTask->pProgress->SetNextOperation(BstrFmt(tr("Unpacking file '%s'"), RTPathFilename(pTask->locInfo.strPath.c_str())), ulWeight);
     1465        vrc = RTTarExtractFiles(pTask->locInfo.strPath.c_str(), pszTmpDir, paFiles, filesList.size(), pTask->updateProgress, &pTask);
     1466        if (RT_FAILURE(vrc))
     1467            throw setError(VBOX_E_FILE_ERROR,
     1468                           tr("Cannot unpack archive file '%s' (%Rrc)"), pTask->locInfo.strPath.c_str(), vrc);
     1469
     1470//        if (!pTask->pProgress.isNull())
     1471//            pTask->pProgress->SetNextOperation(BstrFmt(tr("Importing appliance")), m->ulWeightForXmlOperation);
     1472
     1473        ComObjPtr<Progress> progress;
     1474        /* Import the whole temporary OVF & the disk images */
     1475        LocationInfo li;
     1476        li.strPath = strTmpOvf;
     1477        rc = importImpl(li, progress);
     1478        if (FAILED(rc)) DebugBreakThrow(rc);
     1479
     1480        /* Unlock the appliance for the fs import thread */
     1481        appLock.release();
     1482        /* Wait until the import is done, but report the progress back to the
     1483           caller */
     1484        ComPtr<IProgress> progressInt(progress);
     1485        waitForAsyncProgress(pTask->pProgress, progressInt); /* Any errors will be thrown */
     1486
     1487        /* Again lock the appliance for the next steps */
     1488        appLock.acquire();
     1489    }
     1490    catch(HRESULT aRC)
     1491    {
     1492        rc = aRC;
     1493    }
     1494    /* Delete the temporary files list */
     1495    if (paFiles)
     1496        RTMemFree(paFiles);
     1497    /* Delete all files which where temporary created */
     1498    for (list< pair<Utf8Str, ULONG> >::const_iterator it1 = filesList.begin(); it1 != filesList.end(); ++it1)
     1499    {
     1500        const char *pszFilePath = (*it1).first.c_str();
     1501        if (RTPathExists(pszFilePath))
     1502        {
     1503            vrc = RTFileDelete(pszFilePath);
     1504            if (RT_FAILURE(vrc))
     1505                rc = setError(VBOX_E_FILE_ERROR,
     1506                              tr("Cannot delete file '%s' (%Rrc)"), pszFilePath, vrc);
     1507        }
     1508    }
     1509    /* Delete the temporary directory */
     1510    if (RTPathExists(pszTmpDir))
     1511    {
     1512        vrc = RTDirRemove(pszTmpDir);
     1513        if (RT_FAILURE(vrc))
     1514            rc = setError(VBOX_E_FILE_ERROR,
     1515                          tr("Cannot delete temporary directory '%s' (%Rrc)"), pszTmpDir, vrc);
     1516    }
     1517    if (pszTmpDir)
     1518        RTStrFree(pszTmpDir);
     1519
     1520    LogFlowFunc(("rc=%Rhrc\n", rc));
     1521    LogFlowFuncLeave();
     1522
     1523    return rc;
     1524}
     1525
    12571526/**
    12581527 * Imports one disk image. This is common code shared between
     
    13651634
    13661635            /* Advance to the next operation */
    1367             stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), strSrcFilePath.c_str()),
     1636            stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), RTPathFilename(strSrcFilePath.c_str())),
    13681637                                              di.ulSuggestedSizeMB);     // operation's weight, as set up with the IProgress originally);
    13691638        }
     
    21632432        if (RT_FAILURE(vrc))
    21642433            DebugBreakThrow(setError(VBOX_E_FILE_ERROR,
    2165                                      tr("Cannot create temporary directory '%s'"), pszTmpDir));
     2434                                     tr("Cannot create temporary directory '%s' (%Rrc)"), pszTmpDir, vrc));
    21662435
    21672436        /* Add every disks of every virtual system to an internal list */
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r30881 r31676  
    122122
    123123    void disksWeight();
     124    struct LocationInfo;
    124125    enum SetUpProgressMode { ImportFileWithManifest, ImportFileNoManifest, ImportS3, WriteFile, WriteS3 };
    125     HRESULT setUpProgress(ComObjPtr<Progress> &pProgress,
     126    HRESULT setUpProgress(const LocationInfo &locInfo,
     127                          ComObjPtr<Progress> &pProgress,
    126128                          const Bstr &bstrDescription,
    127129                          SetUpProgressMode mode);
    128130
    129     struct LocationInfo;
    130131    void parseURI(Utf8Str strUri, LocationInfo &locInfo) const;
    131132    void parseBucket(Utf8Str &aPath, Utf8Str &aBucket);
    132     Utf8Str manifestFileName(Utf8Str aPath) const;
     133    Utf8Str manifestFileName(const Utf8Str& aPath) const;
    133134
    134135    HRESULT readImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress);
     
    137138    static DECLCALLBACK(int) taskThreadImportOrExport(RTTHREAD aThread, void *pvUser);
    138139
    139     HRESULT readFS(const LocationInfo &locInfo);
     140    HRESULT readFS(const LocationInfo &locInfo, ComObjPtr<Progress> &pProgress);
     141    HRESULT readFSOVF(const LocationInfo &locInfo, ComObjPtr<Progress> &pProgress);
     142    HRESULT readFSOVA(const LocationInfo &locInfo, ComObjPtr<Progress> &pProgress);
    140143    HRESULT readS3(TaskOVF *pTask);
    141144
     
    149152    HRESULT manifestVerify(const LocationInfo &locInfo, const ovf::OVFReader &reader, ComObjPtr<Progress> &pProgress);
    150153
    151     HRESULT importFS(const LocationInfo &locInfo, ComObjPtr<Progress> &aProgress);
     154    HRESULT importFS(TaskOVF *pTask);
     155    HRESULT importFSOVF(TaskOVF *pTask);
     156    HRESULT importFSOVA(TaskOVF *pTask);
    152157
    153158    struct ImportStack;
     
    175180                                     XMLStack &stack);
    176181
    177     HRESULT writeFS(const LocationInfo &locInfo, const OVFFormat enFormat, ComObjPtr<Progress> &pProgress);
     182    HRESULT writeFS(TaskOVF *pTask);
     183    HRESULT writeFSOVF(TaskOVF *pTask);
     184    HRESULT writeFSOVA(TaskOVF *pTask);
    178185    HRESULT writeS3(TaskOVF *pTask);
    179186
  • trunk/src/VBox/Main/include/ApplianceImplPrivate.h

    r31008 r31676  
    7272
    7373    std::list<Utf8Str>  llWarnings;
    74 
    75     Utf8Str             strManifestFile;    // on import, contains path of manifest file if it exists
    7674
    7775    ULONG               ulWeightForXmlOperation;
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