VirtualBox

Changeset 73892 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Aug 26, 2018 3:30:15 PM (6 years ago)
Author:
vboxsync
Message:

bugref:9152. divided the OCI/OPC/OVF tasks into the separate threads.

Location:
trunk/src/VBox/Main/src-server
Files:
2 edited

Legend:

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

    r73743 r73892  
    12141214}
    12151215
     1216/**
     1217 * Worker for TaskOPC::handler.
     1218 * @thread  pTask       The task.
     1219 */
     1220/* static */
     1221void Appliance::i_exportOPCThreadTask(TaskOPC *pTask)
     1222{
     1223    LogFlowFuncEnter();
     1224    AssertReturnVoid(pTask);
     1225
     1226    Appliance *pAppliance = pTask->pAppliance;
     1227    LogFlowFunc(("Appliance %p taskType=%d\n", pAppliance, pTask->taskType));
     1228
     1229    switch (pTask->taskType)
     1230    {
     1231        case TaskOPC::Export:
     1232            pTask->rc = pAppliance->i_writeFSOPC(pTask);
     1233            break;
     1234
     1235        default:
     1236            AssertFailed();
     1237            pTask->rc = E_FAIL;
     1238            break;
     1239    }
     1240
     1241    if (!pTask->pProgress.isNull())
     1242        pTask->pProgress->i_notifyComplete(pTask->rc);
     1243
     1244    LogFlowFuncLeave();
     1245}
     1246
     1247/* static */
     1248DECLCALLBACK(int) Appliance::TaskOPC::updateProgress(unsigned uPercent, void *pvUser)
     1249{
     1250    Appliance::TaskOPC* pTask = *(Appliance::TaskOPC**)pvUser;
     1251
     1252    if (    pTask
     1253         && !pTask->pProgress.isNull())
     1254    {
     1255        BOOL fCanceled;
     1256        pTask->pProgress->COMGETTER(Canceled)(&fCanceled);
     1257        if (fCanceled)
     1258            return -1;
     1259        pTask->pProgress->SetCurrentOperationProgress(uPercent);
     1260    }
     1261    return VINF_SUCCESS;
     1262}
     1263
     1264/**
     1265 * Worker for TaskOCI::handler.
     1266 * @thread  pTask       The task.
     1267 */
     1268/* static */
     1269void Appliance::i_exportOCIThreadTask(TaskOCI *pTask)
     1270{
     1271    LogFlowFuncEnter();
     1272    AssertReturnVoid(pTask);
     1273
     1274    Appliance *pAppliance = pTask->pAppliance;
     1275    LogFlowFunc(("Appliance %p taskType=%d\n", pAppliance, pTask->taskType));
     1276
     1277    switch (pTask->taskType)
     1278    {
     1279        case TaskOCI::Export:
     1280            pTask->rc = pAppliance->i_writeFSOCI(pTask);
     1281            break;
     1282
     1283        default:
     1284            AssertFailed();
     1285            pTask->rc = E_FAIL;
     1286            break;
     1287    }
     1288
     1289    if (!pTask->pProgress.isNull())
     1290        pTask->pProgress->i_notifyComplete(pTask->rc);
     1291
     1292    LogFlowFuncLeave();
     1293}
     1294
     1295/* static */
     1296DECLCALLBACK(int) Appliance::TaskOCI::updateProgress(unsigned uPercent, void *pvUser)
     1297{
     1298    Appliance::TaskOCI* pTask = *(Appliance::TaskOCI**)pvUser;
     1299
     1300    if (    pTask
     1301         && !pTask->pProgress.isNull())
     1302    {
     1303        BOOL fCanceled;
     1304        pTask->pProgress->COMGETTER(Canceled)(&fCanceled);
     1305        if (fCanceled)
     1306            return -1;
     1307        pTask->pProgress->SetCurrentOperationProgress(uPercent);
     1308    }
     1309    return VINF_SUCCESS;
     1310}
     1311
    12161312void i_parseURI(Utf8Str strUri, LocationInfo &locInfo)
    12171313{
     
    12311327        locInfo.storageType = VFSType_S3;
    12321328        strUri = strUri.substr(sizeof("S3://") - 1);
     1329    }
     1330    else if (strUri.startsWith("OCI://", Utf8Str::CaseInsensitive)) /* OCI service (storage or compute) */
     1331    {
     1332        locInfo.storageType = VFSType_OCI;
     1333        strUri = strUri.substr(sizeof("OCI://") - 1);
    12331334    }
    12341335    else if (strUri.startsWith("webdav://", Utf8Str::CaseInsensitive)) /* webdav service */
     
    14911592    vsde.strRef = strRef;
    14921593    vsde.strOvf = aOvfValue;
    1493     vsde.strVBoxSuggested           // remember original value
    1494         = vsde.strVBoxCurrent       // and set current value which can be overridden by setFinalValues()
     1594    vsde.strVBoxSuggested           /* remember original value */
     1595        = vsde.strVBoxCurrent       /* and set current value which can be overridden by setFinalValues() */
    14951596        = aVBoxValue;
    14961597    vsde.strExtraConfigSuggested
  • trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp

    r73505 r73892  
    645645    }
    646646
     647    HRESULT rc = S_OK;
    647648//  AssertReturn(!(m->optListExport.contains(ExportOptions_CreateManifest)
    648649//  && m->optListExport.contains(ExportOptions_ExportDVDImages)), E_INVALIDARG);
    649650
    650     m->fExportISOImages = m->optListExport.contains(ExportOptions_ExportDVDImages);
    651 
    652     if (!m->fExportISOImages)/* remove all ISO images from VirtualSystemDescription */
    653     {
    654         for (list<ComObjPtr<VirtualSystemDescription> >::const_iterator
    655              it = m->virtualSystemDescriptions.begin();
    656              it != m->virtualSystemDescriptions.end();
    657              ++it)
    658         {
    659             ComObjPtr<VirtualSystemDescription> vsdescThis = *it;
    660             std::list<VirtualSystemDescriptionEntry*> skipped = vsdescThis->i_findByType(VirtualSystemDescriptionType_CDROM);
    661             std::list<VirtualSystemDescriptionEntry*>::const_iterator itSkipped = skipped.begin();
    662             while (itSkipped != skipped.end())
    663             {
    664                 (*itSkipped)->skipIt = true;
    665                 ++itSkipped;
    666             }
    667         }
    668     }
    669 
    670     // do not allow entering this method if the appliance is busy reading or writing
    671     if (!i_isApplianceIdle())
    672         return E_ACCESSDENIED;
    673 
    674     // figure the export format.  We exploit the unknown version value for oracle public cloud.
    675     ovf::OVFVersion_T ovfF;
    676     if (aFormat == "ovf-0.9")
    677         ovfF = ovf::OVFVersion_0_9;
    678     else if (aFormat == "ovf-1.0")
    679         ovfF = ovf::OVFVersion_1_0;
    680     else if (aFormat == "ovf-2.0")
    681         ovfF = ovf::OVFVersion_2_0;
    682     else if (aFormat == "opc-1.0")
    683         ovfF = ovf::OVFVersion_unknown;
     651    /* Parse all necessary info out of the URI */
     652    i_parseURI(aPath, m->locInfo);
     653
     654    if (m->locInfo.storageType == VFSType_OCI)//(isCloudDestination(aPath))
     655    {
     656        rc = S_OK;
     657        ComObjPtr<Progress> progress;
     658        try
     659        {
     660            switch (m->locInfo.storageType)
     661            {
     662                case VFSType_OCI:
     663                    rc = i_writeOCIImpl(m->locInfo, progress);
     664                    break;
     665//              case VFSType_GCP:
     666//                  rc = i_writeGCPImpl(m->locInfo, progress);
     667//                  break;
     668//              case VFSType_Amazon:
     669//                  rc = i_writeAmazonImpl(m->locInfo, progress);
     670//                  break;
     671//              case VFSType_Azure:
     672//                  rc = i_writeAzureImpl(m->locInfo, progress);
     673//                  break;
     674                default:
     675                    break;
     676            }
     677
     678        }
     679        catch (HRESULT aRC)
     680        {
     681            rc = aRC;
     682        }
     683
     684        if (SUCCEEDED(rc))
     685            /* Return progress to the caller */
     686            progress.queryInterfaceTo(aProgress.asOutParam());
     687    }
    684688    else
    685         return setError(VBOX_E_FILE_ERROR,
    686                         tr("Invalid format \"%s\" specified"), aFormat.c_str());
    687 
    688     // Check the extension.
    689     if (ovfF == ovf::OVFVersion_unknown)
    690     {
    691         if (!aPath.endsWith(".tar.gz", Utf8Str::CaseInsensitive))
     689    {
     690        m->fExportISOImages = m->optListExport.contains(ExportOptions_ExportDVDImages);
     691
     692        if (!m->fExportISOImages)/* remove all ISO images from VirtualSystemDescription */
     693        {
     694            for (list<ComObjPtr<VirtualSystemDescription> >::const_iterator
     695                 it = m->virtualSystemDescriptions.begin();
     696                 it != m->virtualSystemDescriptions.end();
     697                 ++it)
     698            {
     699                ComObjPtr<VirtualSystemDescription> vsdescThis = *it;
     700                std::list<VirtualSystemDescriptionEntry*> skipped = vsdescThis->i_findByType(VirtualSystemDescriptionType_CDROM);
     701                std::list<VirtualSystemDescriptionEntry*>::const_iterator itSkipped = skipped.begin();
     702                while (itSkipped != skipped.end())
     703                {
     704                    (*itSkipped)->skipIt = true;
     705                    ++itSkipped;
     706                }
     707            }
     708        }
     709
     710        // do not allow entering this method if the appliance is busy reading or writing
     711        if (!i_isApplianceIdle())
     712            return E_ACCESSDENIED;
     713
     714        // figure the export format.  We exploit the unknown version value for oracle public cloud.
     715        ovf::OVFVersion_T ovfF;
     716        if (aFormat == "ovf-0.9")
     717            ovfF = ovf::OVFVersion_0_9;
     718        else if (aFormat == "ovf-1.0")
     719            ovfF = ovf::OVFVersion_1_0;
     720        else if (aFormat == "ovf-2.0")
     721            ovfF = ovf::OVFVersion_2_0;
     722        else if (aFormat == "opc-1.0")
     723            ovfF = ovf::OVFVersion_unknown;
     724        else
    692725            return setError(VBOX_E_FILE_ERROR,
    693                             tr("OPC appliance file must have .tar.gz extension"));
    694     }
    695     else if (   !aPath.endsWith(".ovf", Utf8Str::CaseInsensitive)
    696              && !aPath.endsWith(".ova", Utf8Str::CaseInsensitive))
    697         return setError(VBOX_E_FILE_ERROR, tr("Appliance file must have .ovf or .ova extension"));
    698 
    699 
    700     /* As of OVF 2.0 we have to use SHA-256 in the manifest. */
    701     m->fManifest = m->optListExport.contains(ExportOptions_CreateManifest);
    702     if (m->fManifest)
    703         m->fDigestTypes = ovfF >= ovf::OVFVersion_2_0 ? RTMANIFEST_ATTR_SHA256 : RTMANIFEST_ATTR_SHA1;
    704     Assert(m->hOurManifest == NIL_RTMANIFEST);
    705 
    706     /* Check whether all passwords are supplied or error out. */
    707     if (m->m_cPwProvided < m->m_vecPasswordIdentifiers.size())
    708         return setError(VBOX_E_INVALID_OBJECT_STATE,
    709                         tr("Appliance export failed because not all passwords were provided for all encrypted media"));
    710 
    711     ComObjPtr<Progress> progress;
    712     HRESULT rc = S_OK;
    713     try
    714     {
    715         /* Parse all necessary info out of the URI */
    716         i_parseURI(aPath, m->locInfo);
    717         rc = i_writeImpl(ovfF, m->locInfo, progress);
    718     }
    719     catch (HRESULT aRC)
    720     {
    721         rc = aRC;
    722     }
    723 
    724     if (SUCCEEDED(rc))
    725         /* Return progress to the caller */
    726         progress.queryInterfaceTo(aProgress.asOutParam());
     726                            tr("Invalid format \"%s\" specified"), aFormat.c_str());
     727
     728        // Check the extension.
     729        if (ovfF == ovf::OVFVersion_unknown)
     730        {
     731            if (!aPath.endsWith(".tar.gz", Utf8Str::CaseInsensitive))
     732                return setError(VBOX_E_FILE_ERROR,
     733                                tr("OPC appliance file must have .tar.gz extension"));
     734        }
     735        else if (   !aPath.endsWith(".ovf", Utf8Str::CaseInsensitive)
     736                 && !aPath.endsWith(".ova", Utf8Str::CaseInsensitive))
     737            return setError(VBOX_E_FILE_ERROR, tr("Appliance file must have .ovf or .ova extension"));
     738
     739
     740        /* As of OVF 2.0 we have to use SHA-256 in the manifest. */
     741        m->fManifest = m->optListExport.contains(ExportOptions_CreateManifest);
     742        if (m->fManifest)
     743            m->fDigestTypes = ovfF >= ovf::OVFVersion_2_0 ? RTMANIFEST_ATTR_SHA256 : RTMANIFEST_ATTR_SHA1;
     744        Assert(m->hOurManifest == NIL_RTMANIFEST);
     745
     746        /* Check whether all passwords are supplied or error out. */
     747        if (m->m_cPwProvided < m->m_vecPasswordIdentifiers.size())
     748            return setError(VBOX_E_INVALID_OBJECT_STATE,
     749                            tr("Appliance export failed because not all passwords were provided for all encrypted media"));
     750
     751        ComObjPtr<Progress> progress;
     752        rc = S_OK;
     753        try
     754        {
     755            /* Parse all necessary info out of the URI */
     756            i_parseURI(aPath, m->locInfo);
     757
     758            switch (ovfF)
     759            {
     760                case ovf::OVFVersion_unknown:
     761                    rc = i_writeOPCImpl(ovfF, m->locInfo, progress);
     762                    break;
     763                default:
     764                    rc = i_writeImpl(ovfF, m->locInfo, progress);
     765                    break;
     766            }
     767
     768        }
     769        catch (HRESULT aRC)
     770        {
     771            rc = aRC;
     772        }
     773
     774        if (SUCCEEDED(rc))
     775            /* Return progress to the caller */
     776            progress.queryInterfaceTo(aProgress.asOutParam());
     777    }
    727778
    728779    return rc;
     
    792843}
    793844
     845
     846HRESULT Appliance::i_writeOCIImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress)
     847{
     848    HRESULT rc;
     849    try
     850    {
     851        //remove all disks from the VirtualSystemDescription exept one
     852        for (list<ComObjPtr<VirtualSystemDescription> >::const_iterator
     853             it = m->virtualSystemDescriptions.begin();
     854             it != m->virtualSystemDescriptions.end();
     855             ++it)
     856        {
     857            ComObjPtr<VirtualSystemDescription> vsdescThis = *it;
     858            std::list<VirtualSystemDescriptionEntry*> skipped = vsdescThis->i_findByType(VirtualSystemDescriptionType_CDROM);
     859            std::list<VirtualSystemDescriptionEntry*>::const_iterator itSkipped = skipped.begin();
     860            while (itSkipped != skipped.end())
     861            {
     862                (*itSkipped)->skipIt = true;
     863                ++itSkipped;
     864            }
     865 
     866            skipped = vsdescThis->i_findByType(VirtualSystemDescriptionType_HardDiskImage);
     867            itSkipped = skipped.begin();
     868            while (itSkipped != skipped.end())
     869            {
     870                Utf8Str path = (*itSkipped)->strVBoxCurrent;
     871                // Locate the Medium object for this entry (by location/path).
     872                Log(("Finding source disk \"%s\"\n", path.c_str()));
     873                ComObjPtr<Medium> ptrSourceDisk;
     874                rc = mVirtualBox->i_findHardDiskByLocation(path, true , &ptrSourceDisk);
     875                ++itSkipped;
     876            }
     877        }
     878
     879        SetUpProgressMode mode;
     880        switch (aLocInfo.storageType)
     881        {
     882            case VFSType_S3:
     883                mode = WriteS3;
     884                break;
     885            case VFSType_OCI:
     886                mode = ExportOCI;
     887                break;
     888
     889            case VFSType_File:
     890                mode = WriteFile;
     891                break;
     892        }
     893        rc = i_setUpProgress(aProgress,
     894                             BstrFmt(tr("Export appliance to Cloud '%s'"), aLocInfo.strPath.c_str()),
     895                             mode);
     896
     897        // Initialize our worker task
     898        TaskOCI* task = NULL;
     899        try
     900        {
     901            task = new Appliance::TaskOCI(this, TaskOCI::Export, aLocInfo, aProgress);
     902        }
     903        catch(...)
     904        {
     905            delete task;
     906            throw rc = setError(VBOX_E_OBJECT_NOT_FOUND,
     907                                tr("Could not create TaskOCI object for exporting to OCI"));
     908        }
     909
     910        rc = task->createThread();
     911        if (FAILED(rc)) throw rc;
     912
     913    }
     914    catch (HRESULT aRC)
     915    {
     916        rc = aRC;
     917    }
     918
     919    return rc;
     920}
     921
     922HRESULT Appliance::i_writeOPCImpl(ovf::OVFVersion_T aFormat, const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress)
     923{
     924    HRESULT rc;
     925    try
     926    {
     927        rc = i_setUpProgress(aProgress,
     928                             BstrFmt(tr("Export appliance '%s'"), aLocInfo.strPath.c_str()),
     929                             (aLocInfo.storageType == VFSType_File) ? WriteFile : WriteS3);
     930
     931        /* Initialize our worker task */
     932        TaskOPC* task = NULL;
     933        try
     934        {
     935            task = new Appliance::TaskOPC(this, TaskOPC::Export, aLocInfo, aProgress);
     936        }
     937        catch(...)
     938        {
     939            delete task;
     940            throw rc = setError(VBOX_E_OBJECT_NOT_FOUND,
     941                                tr("Could not create TaskOPC object for for writing out the OPC to disk"));
     942        }
     943
     944        rc = task->createThread();
     945        if (FAILED(rc)) throw rc;
     946
     947    }
     948    catch (HRESULT aRC)
     949    {
     950        rc = aRC;
     951    }
     952
     953    return rc;
     954}
     955
     956
    794957/**
    795958 * Called from Appliance::i_writeFS() for creating a XML document for this
     
    9861149            // output filename
    9871150            const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf;
     1151
    9881152            // target path needs to be composed from where the output OVF is
    9891153            Utf8Str strTargetFilePath(strPath);
     
    19822146    m->state = Data::ApplianceExporting;
    19832147
    1984     if (pTask->enFormat == ovf::OVFVersion_unknown)
    1985         rc = i_writeFSOPC(pTask, multiLock);
    1986     else if (pTask->locInfo.strPath.endsWith(".ovf", Utf8Str::CaseInsensitive))
     2148    if (pTask->locInfo.strPath.endsWith(".ovf", Utf8Str::CaseInsensitive))
    19872149        rc = i_writeFSOVF(pTask, multiLock);
    19882150    else
     
    20882250
    20892251/**
     2252 * Upload the image to the OCI Storage service, next import the
     2253 * uploaded image into internal OCI image format and launch an
     2254 * instance with this image in the OCI Compute service.
     2255 */
     2256HRESULT Appliance::i_writeFSOCI(TaskOCI *pTask)
     2257{
     2258    LogFlowFuncEnter();
     2259    HRESULT hrc = S_OK;
     2260
     2261    return hrc;
     2262}
     2263
     2264/**
    20902265 * Writes the Oracle Public Cloud appliance.
    20912266 *
     
    20932268 * to save diskspace on the target host system.
    20942269 */
    2095 HRESULT Appliance::i_writeFSOPC(TaskOVF *pTask, AutoWriteLockBase &writeLock)
     2270HRESULT Appliance::i_writeFSOPC(TaskOPC *pTask)
    20962271{
    20972272    LogFlowFuncEnter();
    20982273    HRESULT hrc = S_OK;
     2274
     2275    // Lock the media tree early to make sure nobody else tries to make changes
     2276    // to the tree. Also lock the IAppliance object for writing.
     2277    AutoMultiWriteLock2 multiLock(&mVirtualBox->i_getMediaTreeLockHandle(), this->lockHandle() COMMA_LOCKVAL_SRC_POS);
     2278    // Additional protect the IAppliance object, cause we leave the lock
     2279    // when starting the disk export and we don't won't block other
     2280    // callers on this lengthy operations.
     2281    m->state = Data::ApplianceExporting;
    20992282
    21002283    /*
     
    21102293    {
    21112294        xml::Document doc;
    2112         i_buildXML(writeLock, doc, stack, pTask->locInfo.strPath, ovf::OVFVersion_2_0);
     2295        i_buildXML(multiLock, doc, stack, pTask->locInfo.strPath, ovf::OVFVersion_2_0);
    21132296    }
    21142297
     
    21692352        if (cTarballs > 0)
    21702353        {
    2171 
    21722354            strTarballPath.stripFilename().append(RTPATH_SLASH_STR).append(pDiskEntry->strOvf);
    21732355            const char *pszExt = RTPathSuffix(pDiskEntry->strOvf.c_str());
     
    22162398                 * leave the appliance lock.
    22172399                 */
    2218                 writeLock.release();
     2400                multiLock.release();
    22192401
    22202402                pTask->pProgress->SetNextOperation(BstrFmt(tr("Exporting to disk image '%Rbn'"), strTarballPath.c_str()).raw(),
     
    22242406                                                   pTask->pProgress, true /*fSparse*/);
    22252407
    2226                 writeLock.acquire();
     2408                multiLock.acquire();
    22272409                if (SUCCEEDED(hrc))
    22282410                {
     
    22682450            RTFileDelete(it->c_str());
    22692451
     2452    // reset the state so others can call methods again
     2453    m->state = Data::ApplianceIdle;
     2454
    22702455    LogFlowFuncLeave();
    22712456    return hrc;
     
    23802565            // output filename
    23812566            const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf;
     2567
    23822568            // target path needs to be composed from where the output OVF is
    23832569            const Utf8Str &strTargetFilePath = strTargetFileNameOnly;
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