VirtualBox

Changeset 17646 in vbox


Ignore:
Timestamp:
Mar 10, 2009 5:47:31 PM (16 years ago)
Author:
vboxsync
Message:

OVF: add actual image export

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/com/string.h

    r17634 r17646  
    409409    }
    410410
     411    void append(const Utf8Str &that)
     412    {
     413        size_t cbThis = length();
     414        size_t cbThat = that.length();
     415
     416        if (cbThat)
     417        {
     418            size_t cbBoth = cbThis + cbThat + 1;
     419
     420            // @todo optimize
     421            char *pszTemp;
     422#if !defined (VBOX_WITH_XPCOM)
     423            pszTemp = (char*)::RTMemTmpAlloc(cbBoth);
     424#else
     425            pszTemp = (char*)nsMemory::Alloc(cbBoth);
     426#endif
     427            if (str)
     428            {
     429                memcpy(pszTemp, str, cbThis);
     430                setNull();
     431            }
     432            if (that.str)
     433                memcpy(pszTemp + cbThis, that.str, cbThat);
     434            pszTemp[cbThis + cbThat] = '\0';
     435
     436            str = pszTemp;
     437        }
     438    }
     439
    411440    int compare (const char *s) const
    412441    {
  • trunk/src/VBox/Main/ApplianceImpl.cpp

    r17636 r17646  
    228228};
    229229
    230 struct Appliance::TaskExportOVF
    231 {
    232     TaskExportOVF(Appliance *aThat, Progress *aProgress)
     230struct Appliance::TaskWriteOVF
     231{
     232    TaskWriteOVF(Appliance *aThat, Progress *aProgress)
    233233        : pAppliance(aThat)
    234234        , progress(aProgress)
    235235        , rc(S_OK)
    236236    {}
    237     ~TaskExportOVF() {}
     237    ~TaskWriteOVF() {}
    238238
    239239    HRESULT startThread();
     
    412412}
    413413
    414 HRESULT Appliance::TaskExportOVF::startThread()
    415 {
    416     int vrc = RTThreadCreate(NULL, Appliance::taskThreadExportOVF, this,
     414HRESULT Appliance::TaskWriteOVF::startThread()
     415{
     416    int vrc = RTThreadCreate(NULL, Appliance::taskThreadWriteOVF, this,
    417417                             0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
    418418                             "Appliance::Task");
     
    16471647
    16481648        /* Initialize our worker task */
    1649         std::auto_ptr<TaskExportOVF> task(new TaskExportOVF(this, progress));
     1649        std::auto_ptr<TaskWriteOVF> task(new TaskWriteOVF(this, progress));
    16501650        //AssertComRCThrowRC (task->autoCaller.rc());
    16511651
     
    23582358
    23592359/**
    2360  * Worker thread implementation for ImportMachines().
     2360 * Worker thread implementation for Write() (ovf writer).
    23612361 * @param aThread
    23622362 * @param pvUser
    23632363 */
    23642364/* static */
    2365 DECLCALLBACK(int) Appliance::taskThreadExportOVF(RTTHREAD aThread, void *pvUser)
    2366 {
    2367     std::auto_ptr<TaskImportMachines> task(static_cast<TaskImportMachines*>(pvUser));
     2365DECLCALLBACK(int) Appliance::taskThreadWriteOVF(RTTHREAD aThread, void *pvUser)
     2366{
     2367    std::auto_ptr<TaskWriteOVF> task(static_cast<TaskWriteOVF*>(pvUser));
    23682368    AssertReturn(task.get(), VERR_GENERAL_FAILURE);
    23692369
     
    24122412        // @todo for each disk:
    24132413        // xml::ElementNode *pelmDisk = pelmDiskSection->createChild("Disk");
     2414        // for now, set up a map so we have a list of unique disk names (to make
     2415        // sure the same disk name is only added once)
     2416        map<Utf8Str, const VirtualSystemDescriptionEntry*> mapDisks;
    24142417
    24152418        /* <Envelope>/<NetworkSection>:
     
    26362639                            if (uLoop == 2)
    26372640                            {
     2641                                Utf8Str strDiskID = Utf8StrFmt("vmdisk%RI32", ++cDisks);
     2642
    26382643                                strDescription = "Disk Image";
    2639                                 strCaption = Utf8StrFmt("disk%d", ++cDisks);
     2644                                strCaption = Utf8StrFmt("disk%RI32", cDisks);        // this is not used for anything else
    26402645                                type = OVFResourceType_HardDisk; // 17
    2641                                 strHostResource = desc.strOvf;
     2646
     2647                                // the following references the "<Disks>" XML block
     2648                                strHostResource = Utf8StrFmt("/disk/%s", strDiskID.c_str());
     2649
    26422650                                // “controller=<index>;channel=<c>“
    26432651                                size_t pos1 = desc.strExtraConfig.find("controller=");
     
    26622670                                    throw setError(VBOX_E_NOT_SUPPORTED,
    26632671                                                   tr("Missing or bad extra config string in hard disk image: \"%s\""), desc.strExtraConfig.c_str());
     2672
     2673                                mapDisks[strDiskID] = &desc;
    26642674                            }
    26652675                        break;
     
    28102820            pelmNetwork->setAttribute("ovf:name", strNetwork.c_str());
    28112821            pelmNetwork->createChild("Description")->addContent("Logical network used by this appliance.");
     2822        }
     2823
     2824        map<Utf8Str, const VirtualSystemDescriptionEntry*>::const_iterator itS;
     2825        uint32_t ulFile = 1;
     2826        for (itS = mapDisks.begin();
     2827             itS != mapDisks.end();
     2828             ++itS)
     2829        {
     2830            const Utf8Str &strDiskID = itS->first;
     2831            const VirtualSystemDescriptionEntry *pDiskEntry = itS->second;
     2832
     2833            // source path: where the VBox image is
     2834            const Utf8Str &strSrcFilePath = pDiskEntry->strVbox;
     2835            const Bstr bstrSrcFilePath(strSrcFilePath);
     2836            if (!RTPathExists(strSrcFilePath.c_str()))
     2837                /* This isn't allowed */
     2838                throw setError(VBOX_E_FILE_ERROR,
     2839                                tr("Source virtual disk image file '%s' doesn't exist"),
     2840                                    strSrcFilePath.c_str());
     2841
     2842            // output filename
     2843            const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf;
     2844            // target path needs to be composed from where the output OVF is
     2845            Utf8Str strTargetFilePath = stripFilename(pAppliance->m->strPath);
     2846            strTargetFilePath.append("/");
     2847            strTargetFilePath.append(strTargetFileNameOnly);
     2848
     2849            // clone the disk:
     2850            ComPtr<IHardDisk> pSourceDisk;
     2851            ComPtr<IHardDisk> pTargetDisk;
     2852            ComPtr<IProgress> pProgress2;
     2853
     2854            Log(("Finding source disk \"%ls\"\n", bstrSrcFilePath.raw()));
     2855            rc = pVirtualBox->FindHardDisk(bstrSrcFilePath, pSourceDisk.asOutParam());
     2856            if (FAILED(rc)) throw rc;
     2857
     2858            /* We need the format description of the source disk image */
     2859            Bstr bstrSrcFormat;
     2860            rc = pSourceDisk->COMGETTER(Format)(bstrSrcFormat.asOutParam());
     2861            if (FAILED(rc)) throw rc;
     2862            /* Create a new hard disk interface for the destination disk image */
     2863            Log(("Creating target disk \"%s\"\n", strTargetFilePath.raw()));
     2864            rc = pVirtualBox->CreateHardDisk(bstrSrcFormat, Bstr(strTargetFilePath), pTargetDisk.asOutParam());
     2865            if (FAILED(rc)) throw rc;
     2866            /* Clone the source disk image */
     2867            rc = pSourceDisk->CloneTo(pTargetDisk, pProgress2.asOutParam());
     2868            if (FAILED(rc)) throw rc;
     2869
     2870            /* Advance to the next operation */
     2871            if (!task->progress.isNull())
     2872                task->progress->advanceOperation(BstrFmt(tr("Importing virtual disk image '%s'"), strSrcFilePath.c_str()));
     2873
     2874            // now loop until the asynchronous operation completes and then
     2875            // report its result
     2876            BOOL fCompleted;
     2877            LONG currentPercent;
     2878            while (SUCCEEDED(pProgress2->COMGETTER(Completed(&fCompleted))))
     2879            {
     2880                rc = pProgress2->COMGETTER(Percent(&currentPercent));
     2881                if (FAILED(rc)) throw rc;
     2882                if (!task->progress.isNull())
     2883                    task->progress->notifyProgress(currentPercent);
     2884                if (fCompleted)
     2885                    break;
     2886                /* Make sure the loop is not too tight */
     2887                rc = pProgress2->WaitForCompletion(100);
     2888                if (FAILED(rc)) throw rc;
     2889            }
     2890            // report result of asynchronous operation
     2891            HRESULT vrc;
     2892            rc = pProgress2->COMGETTER(ResultCode)(&vrc);
     2893            if (FAILED(rc)) throw rc;
     2894
     2895            // if the thread of the progress object has an error, then
     2896            // retrieve the error info from there, or it'll be lost
     2897            if (FAILED(vrc))
     2898            {
     2899                com::ErrorInfo info(pProgress2);
     2900                const char *pcsz = Utf8Str(info.getText()).c_str();
     2901                HRESULT rc2 = setError(vrc, pcsz);
     2902                throw rc2;
     2903            }
     2904
     2905            // we need the capacity and actual file size for the XML
     2906            uint64_t cbFile = 12345678; // @todo
     2907            uint64_t cbCapacity = 2345678; // @todo
     2908
     2909            // now handle the XML for the disk:
     2910            Utf8StrFmt strFileRef("file%RI32", ulFile++);
     2911            // <File ovf:href="WindowsXpProfessional-disk1.vmdk" ovf:id="file1" ovf:size="1710381056"/>
     2912            xml::ElementNode *pelmFile = pelmReferences->createChild("File");
     2913            pelmFile->setAttribute("ovf:href", strTargetFileNameOnly);
     2914            pelmFile->setAttribute("ovf:id", strFileRef);
     2915            pelmFile->setAttribute("ovf:size", Utf8StrFmt("%RI64", cbFile).c_str()); // @todo
     2916
     2917            // add disk to XML Disks section
     2918            // <Disk ovf:capacity="8589934592" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/specifications/vmdk.html#sparse"/>
     2919            xml::ElementNode *pelmDisk = pelmDiskSection->createChild("Disk");
     2920            pelmDisk->setAttribute("ovf:capacity", Utf8StrFmt("%RI64", cbCapacity).c_str()); // @todo
     2921            pelmDisk->setAttribute("ovf:diskId", strDiskID);
     2922            pelmDisk->setAttribute("ovf:fileRef", strFileRef);
     2923            pelmDisk->setAttribute("ovf:format", "http://www.vmware.com/specifications/vmdk.html#sparse");
    28122924        }
    28132925
     
    33523464            }
    33533465
     3466            Utf8Str strTargetVmdkName(bstrName);
     3467            RTPathStripExt(strTargetVmdkName.mutableRaw());
     3468            strTargetVmdkName.append(".vmdk");
     3469
    33543470            pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskImage,
    3355                                Utf8Str(bstrName), // disk ID: let's use the name
    3356                                "",                // OVF value: unknown as of now
     3471                               strTargetVmdkName,  // disk ID: let's use the name
     3472                               strTargetVmdkName,   // OVF value:
    33573473                               Utf8Str(bstrLocation), // vbox value: media path
    33583474                               Utf8StrFmt("controller=%RI32;channel=%RI32", lControllerVsys, lChannelVsys));
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r17634 r17646  
    101101    static DECLCALLBACK(int) taskThreadImportMachines(RTTHREAD thread, void *pvUser);
    102102
    103     struct TaskExportOVF;       /* Worker thread for export */
    104     static DECLCALLBACK(int) taskThreadExportOVF(RTTHREAD thread, void *pvUser);
     103    struct TaskWriteOVF;       /* Worker thread for export */
     104    static DECLCALLBACK(int) taskThreadWriteOVF(RTTHREAD thread, void *pvUser);
    105105
    106106    friend class Machine;
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