VirtualBox

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


Ignore:
Timestamp:
Jun 1, 2017 11:50:09 AM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
115885
Message:

Main: ApplianceImplExport.cpp: More hacking on OPC exporting.

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

Legend:

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

    r67197 r67203  
    22062206{
    22072207    LogFlowFuncEnter();
     2208    HRESULT hrc = S_OK;
    22082209
    22092210    /*
    2210      * Open the output file, pipe it thru gzip and attach a TAR creator.
     2211     * We're duplicating parts of i_writeFSImpl here because that's simpler
     2212     * and creates less spaghetti code.
    22112213     */
    2212     HRESULT hrc;
    2213     RTVFSIOSTREAM hVfsIosFile;
    2214     int vrc = RTVfsIoStrmOpenNormal(pTask->locInfo.strPath.c_str(),
    2215                                     RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
    2216                                     &hVfsIosFile);
    2217     if (RT_SUCCESS(vrc))
    2218     {
    2219 
    2220         RTVFSIOSTREAM hVfsIosGzip;
    2221         vrc = RTZipGzipCompressIoStream(hVfsIosFile, 0 /*fFlags*/, 6 /*uLevel*/, &hVfsIosGzip);
    2222         RTVfsIoStrmRelease(hVfsIosFile);
    2223         if (RT_SUCCESS(vrc))
    2224         {
    2225 
    2226             RTVFSFSSTREAM hVfsFssTar;
    2227             vrc = RTZipTarFsStreamToIoStream(hVfsIosGzip, RTZIPTARFORMAT_GNU, RTZIPTAR_C_SPARSE, &hVfsFssTar);
     2214    std::list<Utf8Str> lstTarballs;
     2215    try
     2216    {
     2217        /*
     2218         * Use i_buildXML to build a stack of disk images.  We don't care about the XML doc here.
     2219         */
     2220        XMLStack stack;
     2221        {
     2222            xml::Document doc;
     2223            i_buildXML(writeLock, doc, stack, pTask->locInfo.strPath, ovf::OVFVersion_2_0);
     2224        }
     2225
     2226        /*
     2227         * Process the disk images.
     2228         */
     2229        unsigned cTarballs = 0;
     2230        for (list<Utf8Str>::const_iterator it = stack.mapDiskSequence.begin();
     2231             it != stack.mapDiskSequence.end();
     2232             ++it)
     2233        {
     2234            const Utf8Str                       &strDiskID = *it;
     2235            const VirtualSystemDescriptionEntry *pDiskEntry = stack.mapDisks[strDiskID];
     2236            const Utf8Str                       &strSrcFilePath = pDiskEntry->strVBoxCurrent;  // where the VBox image is
     2237
     2238            /*
     2239             * Some skipping.
     2240             */
     2241            if (pDiskEntry->skipIt)
     2242                continue;
     2243
     2244            /* Skip empty media (DVD-ROM, floppy). */
     2245            if (strSrcFilePath.isEmpty())
     2246                continue;
     2247
     2248            /* Only deal with harddisk and DVD-ROMs, skip any floppies for now. */
     2249            if (   pDiskEntry->type != VirtualSystemDescriptionType_HardDiskImage
     2250                && pDiskEntry->type != VirtualSystemDescriptionType_CDROM)
     2251                continue;
     2252
     2253            /*
     2254             * Locate the Medium object for this entry (by location/path).
     2255             */
     2256            Log(("Finding source disk \"%s\"\n", strSrcFilePath.c_str()));
     2257            ComObjPtr<Medium> ptrSourceDisk;
     2258            if (pDiskEntry->type == VirtualSystemDescriptionType_HardDiskImage)
     2259                hrc = mVirtualBox->i_findHardDiskByLocation(strSrcFilePath, true, &ptrSourceDisk);
     2260            else
     2261                hrc = mVirtualBox->i_findDVDOrFloppyImage(DeviceType_DVD, NULL /*aId*/, strSrcFilePath,
     2262                                                          true /*aSetError*/, &ptrSourceDisk);
     2263            if (FAILED(hrc))
     2264                throw hrc;
     2265            if (strSrcFilePath.isEmpty())
     2266                continue;
     2267
     2268            /*
     2269             * Figure out the names.
     2270             */
     2271
     2272            /* The name inside the tarball.  Replace the suffix of harddisk images with ".img". */
     2273            Utf8Str strInsideName = pDiskEntry->strOvf;
     2274            if (pDiskEntry->type == VirtualSystemDescriptionType_HardDiskImage)
     2275                strInsideName.stripSuffix().append(".img");
     2276
     2277            /* The first tarball we create uses the specified name. Subsequent
     2278               takes the name from the disk entry or something. */
     2279            Utf8Str strTarballPath = pTask->locInfo.strPath;
     2280            if (cTarballs > 0)
     2281            {
     2282                /** @todo test this stuff   */
     2283                const char *pszExt = RTPathSuffix(pDiskEntry->strOvf.c_str());
     2284                pszExt = !pszExt || *pszExt == '.' ? "" : pszExt + 1;
     2285
     2286                strTarballPath.stripFilename().append(RTPATH_SLASH_STR).append(pDiskEntry->strOvf);
     2287                strTarballPath.stripSuffix().append("_").append(pszExt).append(".tar.gz");
     2288
     2289            }
     2290            cTarballs++;
     2291
     2292            /*
     2293             * Create the tar output stream.
     2294             */
     2295            RTVFSIOSTREAM hVfsIosFile;
     2296            int vrc = RTVfsIoStrmOpenNormal(strTarballPath.c_str(),
     2297                                            RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
     2298                                            &hVfsIosFile);
     2299            if (RT_FAILURE(vrc))
     2300                throw setErrorVrc(vrc, tr("Failed to create '%s' (%Rrc)"), strTarballPath.c_str(), vrc);
     2301
     2302            RTVFSIOSTREAM hVfsIosGzip;
     2303            vrc = RTZipGzipCompressIoStream(hVfsIosFile, 0 /*fFlags*/, 6 /*uLevel*/, &hVfsIosGzip);
     2304            RTVfsIoStrmRelease(hVfsIosFile);
     2305
     2306            RTVFSFSSTREAM hVfsFssTar = NIL_RTVFSFSSTREAM;
     2307            if (RT_SUCCESS(vrc))
     2308                vrc = RTZipTarFsStreamToIoStream(hVfsIosGzip, RTZIPTARFORMAT_GNU, RTZIPTAR_C_SPARSE, &hVfsFssTar);
    22282309            RTVfsIoStrmRelease(hVfsIosGzip);
    2229             if (RT_SUCCESS(vrc))
     2310
     2311            if (RT_FAILURE(vrc))
    22302312            {
     2313                RTFileDelete(strTarballPath.c_str());
     2314                throw setErrorVrc(vrc, tr("Failed to TAR creator instance for '%s' (%Rrc)"), strTarballPath.c_str(), vrc);
     2315            }
     2316
     2317            /*
     2318             * The exporting requests a lock on the media tree. So temporarily
     2319             * leave the appliance lock.
     2320             */
     2321            writeLock.release();
     2322
     2323            try
     2324            {
     2325                /* advance to the next operation */
     2326                pTask->pProgress->SetNextOperation(BstrFmt(tr("Exporting to disk image '%Rbn'"), strTarballPath.c_str()).raw(),
     2327                                                   pDiskEntry->ulSizeMB);     // operation's weight, as set up
     2328                                                                              // with the IProgress originally
     2329                ///*
     2330                // * We threat the harddisks are raw images, but since they typically
     2331                // * require a lot more setup and configuration compares to ISOs, we
     2332                // * don't bother trying sharing code here (yet).
     2333                // */
     2334                //if (pDiskEntry->type == VirtualSystemDescriptionType_HardDiskImage)
     2335                    hrc = ptrSourceDisk->i_addRawToFss(strInsideName.c_str(), m->m_pSecretKeyStore, hVfsFssTar /*, pProgress2*/);
     2336                //else if (pDiskEntry->type == VirtualSystemDescriptionType_CDROM)
     2337                //{
     2338                //    /* Open the source image and cast it to a VFS base object. */
     2339                //    RTVFSFILE hVfsSrcFile;
     2340                //    vrc = RTVfsFileOpenNormal(strSrcFilePath.c_str(),
     2341                //                              RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE,
     2342                //                              &hVfsSrcFile);
     2343                //    if (RT_FAILURE(vrc))
     2344                //        throw setErrorBoth(VBOX_E_FILE_ERROR, vrc,
     2345                //                           tr("Could not create or open file '%s' (%Rrc)"), strSrcFilePath.c_str(), vrc);
     2346                //
     2347                //    RTVFSOBJ hVfsSrc = RTVfsObjFromFile(hVfsSrcFile);
     2348                //    RTVfsFileRelease(hVfsSrcFile);
     2349                //    AssertStmt(hVfsSrc != NIL_RTVFSOBJ, throw VERR_INTERNAL_ERROR);
     2350                //
     2351                //    /* Add it to the output stream.  This will pull in all the data from the object. */
     2352                //    vrc = RTVfsFsStrmAdd(hVfsFssTar, strInsideName.c_str(), hVfsSrc, 0 /*fFlags*/);
     2353                //    RTVfsObjRelease(hVfsSrc);
     2354                //    if (RT_FAILURE(vrc))
     2355                //        throw setErrorBoth(VBOX_E_FILE_ERROR, vrc,  tr("Error during copy CD/DVD image '%s' (%Rrc)"),
     2356                //                           strSrcFilePath.c_str(), vrc);
     2357                //}
     2358                //else
     2359                //    AssertFailedStmt(throw E_UNEXPECTED);
     2360                if (FAILED(hrc))
     2361                    throw hrc;
     2362
    22312363                /*
    2232                  * Before we do the actual writing, disable OVF and manifest creation.
     2364                 * Complete and close the tarball.
    22332365                 */
    2234                 bool fManifestSaved = m->fManifest;
    2235                 m->fManifest = false;
    2236 
    2237                 hrc = i_writeFSImpl(pTask, writeLock, hVfsFssTar, false /*fOvfFile*/, false /*fStreamOptimizedVmdk*/);
     2366                vrc = RTVfsFsStrmEnd(hVfsFssTar);
    22382367                RTVfsFsStrmRelease(hVfsFssTar);
    2239 
    2240                 m->fManifest = fManifestSaved;
     2368                hVfsFssTar = NIL_RTVFSFSSTREAM;
     2369                if (RT_FAILURE(vrc))
     2370                    throw setErrorBoth(VBOX_E_FILE_ERROR, vrc,
     2371                                       tr("Error completing TAR file '%s' (%Rrc)"), strTarballPath.c_str(), vrc);
     2372
     2373                /* Remember the tarball name for cleanup. */
     2374                try { lstTarballs.push_back(strTarballPath.c_str()); }
     2375                catch (std::bad_alloc) { throw E_OUTOFMEMORY; }
    22412376            }
    2242             else
    2243                 hrc = setErrorVrc(vrc, tr("Failed create TAR creator for '%s' (%Rrc)"), pTask->locInfo.strPath.c_str(), vrc);
    2244         }
    2245         else
    2246             hrc = setErrorVrc(vrc, tr("Failed create gzipper for '%s' (%Rrc)"), pTask->locInfo.strPath.c_str(), vrc);
    2247 
    2248         /* Delete the OVA on failure. */
    2249         if (FAILED(hrc))
    2250             RTFileDelete(pTask->locInfo.strPath.c_str());
    2251     }
    2252     else
    2253         hrc = setErrorVrc(vrc, tr("Failed to open '%s' for writing (%Rrc)"), pTask->locInfo.strPath.c_str(), vrc);
     2377            catch (HRESULT hrc3)
     2378            {
     2379                writeLock.acquire();
     2380                RTVfsFsStrmRelease(hVfsFssTar);
     2381                RTFileDelete(strTarballPath.c_str());
     2382                throw hrc3;
     2383            }
     2384
     2385            // Finished, lock again (so nobody mess around with the medium tree
     2386            // in the meantime)
     2387            writeLock.acquire();
     2388        }
     2389    }
     2390    catch (HRESULT hrc2)
     2391    {
     2392        hrc = hrc2;
     2393    }
     2394
     2395    /*
     2396     * Delete output files on failure.
     2397     */
     2398    if (FAILED(hrc))
     2399        for (list<Utf8Str>::const_iterator it = lstTarballs.begin(); it != lstTarballs.end(); ++it)
     2400            RTFileDelete(it->c_str());
    22542401
    22552402    LogFlowFuncLeave();
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r67184 r67203  
    60926092    }
    60936093    catch (HRESULT aRC) { rc = aRC; }
     6094
     6095    return rc;
     6096}
     6097
     6098/**
     6099 *
     6100 * @note    Similar code exists in i_taskExportHandler.
     6101 */
     6102HRESULT Medium::i_addRawToFss(const char *aFilename, SecretKeyStore *pKeyStore,
     6103                              RTVFSFSSTREAM hVfsFssDst /*, const ComObjPtr<Progress> &aProgress*/)
     6104{
     6105
     6106    //RT_NOREF(aProgress); /** @todo fix progress object. */
     6107
     6108    /*
     6109     * Build the source lock list.
     6110     */
     6111    MediumLockList SourceMediumLockList;
     6112    HRESULT rc = i_createMediumLockList(true /* fFailIfInaccessible */,
     6113                                        NULL /* pToLockWrite */,
     6114                                        false /* fMediumLockWriteAll */,
     6115                                        NULL,
     6116                                        SourceMediumLockList);
     6117    if (FAILED(rc))
     6118        return rc;
     6119
     6120    try
     6121    {
     6122        /*
     6123         * Lock all in {parent,child} order.
     6124         */
     6125        ComObjPtr<Medium> pBase = i_getBase();
     6126        AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
     6127
     6128        PVDISK hdd;
     6129        int vrc = VDCreate(m->vdDiskIfaces, i_convertDeviceType(), &hdd);
     6130        ComAssertRCThrow(vrc, E_FAIL);
     6131
     6132        try
     6133        {
     6134            settings::StringsMap::iterator itKeyStore = pBase->m->mapProperties.find("CRYPT/KeyStore");
     6135            if (itKeyStore != pBase->m->mapProperties.end())
     6136            {
     6137                settings::StringsMap::iterator itKeyId = pBase->m->mapProperties.find("CRYPT/KeyId");
     6138
     6139#ifdef VBOX_WITH_EXTPACK
     6140                ExtPackManager *pExtPackManager = m->pVirtualBox->i_getExtPackManager();
     6141                if (pExtPackManager->i_isExtPackUsable(ORACLE_PUEL_EXTPACK_NAME))
     6142                {
     6143                    /* Load the plugin */
     6144                    Utf8Str strPlugin;
     6145                    rc = pExtPackManager->i_getLibraryPathForExtPack(g_szVDPlugin, ORACLE_PUEL_EXTPACK_NAME, &strPlugin);
     6146                    if (SUCCEEDED(rc))
     6147                    {
     6148                        vrc = VDPluginLoadFromFilename(strPlugin.c_str());
     6149                        if (RT_FAILURE(vrc))
     6150                            throw setError(VBOX_E_NOT_SUPPORTED,
     6151                                           tr("Retrieving encryption settings of the image failed because the encryption plugin could not be loaded (%s)"),
     6152                                           i_vdError(vrc).c_str());
     6153                    }
     6154                    else
     6155                        throw setError(VBOX_E_NOT_SUPPORTED,
     6156                                       tr("Encryption is not supported because the extension pack '%s' is missing the encryption plugin (old extension pack installed?)"),
     6157                                       ORACLE_PUEL_EXTPACK_NAME);
     6158                }
     6159                else
     6160                    throw setError(VBOX_E_NOT_SUPPORTED,
     6161                                   tr("Encryption is not supported because the extension pack '%s' is missing"),
     6162                                   ORACLE_PUEL_EXTPACK_NAME);
     6163#else
     6164                throw setError(VBOX_E_NOT_SUPPORTED,
     6165                               tr("Encryption is not supported because extension pack support is not built in"));
     6166#endif
     6167
     6168                if (itKeyId == pBase->m->mapProperties.end())
     6169                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
     6170                                   tr("Image '%s' is configured for encryption but doesn't has a key identifier set"),
     6171                                   pBase->m->strLocationFull.c_str());
     6172
     6173                /* Find the proper secret key in the key store. */
     6174                if (!pKeyStore)
     6175                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
     6176                                   tr("Image '%s' is configured for encryption but there is no key store to retrieve the password from"),
     6177                                   pBase->m->strLocationFull.c_str());
     6178
     6179                SecretKey *pKey = NULL;
     6180                vrc = pKeyStore->retainSecretKey(itKeyId->second, &pKey);
     6181                if (RT_FAILURE(vrc))
     6182                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
     6183                                   tr("Failed to retrieve the secret key with ID \"%s\" from the store (%Rrc)"),
     6184                                   itKeyId->second.c_str(), vrc);
     6185
     6186                Medium::CryptoFilterSettings CryptoSettingsRead;
     6187                i_taskEncryptSettingsSetup(&CryptoSettingsRead, NULL, itKeyStore->second.c_str(), (const char *)pKey->getKeyBuffer(),
     6188                                           false /* fCreateKeyStore */);
     6189                vrc = VDFilterAdd(hdd, "CRYPT", VD_FILTER_FLAGS_READ, CryptoSettingsRead.vdFilterIfaces);
     6190                pKeyStore->releaseSecretKey(itKeyId->second);
     6191                if (vrc == VERR_VD_PASSWORD_INCORRECT)
     6192                    throw setError(VBOX_E_PASSWORD_INCORRECT, tr("The password to decrypt the image is incorrect"));
     6193                if (RT_FAILURE(vrc))
     6194                    throw setError(VBOX_E_INVALID_OBJECT_STATE, tr("Failed to load the decryption filter: %s"),
     6195                                   i_vdError(vrc).c_str());
     6196            }
     6197
     6198            /* Open all media in the source chain. */
     6199            MediumLockList::Base::const_iterator sourceListBegin = SourceMediumLockList.GetBegin();
     6200            MediumLockList::Base::const_iterator sourceListEnd = SourceMediumLockList.GetEnd();
     6201            for (MediumLockList::Base::const_iterator it = sourceListBegin; it != sourceListEnd; ++it)
     6202            {
     6203                const MediumLock &mediumLock = *it;
     6204                const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
     6205                AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
     6206
     6207                /* sanity check */
     6208                Assert(pMedium->m->state == MediumState_LockedRead);
     6209
     6210                /* Open all media in read-only mode. */
     6211                vrc = VDOpen(hdd,
     6212                             pMedium->m->strFormat.c_str(),
     6213                             pMedium->m->strLocationFull.c_str(),
     6214                             VD_OPEN_FLAGS_READONLY | m->uOpenFlagsDef,
     6215                             pMedium->m->vdImageIfaces);
     6216                if (RT_FAILURE(vrc))
     6217                    throw setError(VBOX_E_FILE_ERROR,
     6218                                   tr("Could not open the medium storage unit '%s'%s"),
     6219                                   pMedium->m->strLocationFull.c_str(),
     6220                                   i_vdError(vrc).c_str());
     6221            }
     6222
     6223            Assert(m->state == MediumState_LockedRead);
     6224
     6225            /* unlock before the potentially lengthy operation */
     6226            thisLock.release();
     6227
     6228            /*
     6229             * Create a VFS file interface to the HDD.
     6230             */
     6231            RTVFSFILE hVfsFile = NIL_RTVFSFILE;
     6232            vrc = VDCreateVfsFileFromDisk(hdd, 0 /*fFlags*/, &hVfsFile);
     6233            if (RT_SUCCESS(vrc))
     6234            {
     6235                RTVFSOBJ hVfsObj = RTVfsObjFromFile(hVfsFile);
     6236                RTVfsFileRelease(hVfsFile);
     6237                vrc = RTVfsFsStrmAdd(hVfsFssDst, aFilename, hVfsObj, 0 /*fFlags*/);
     6238                RTVfsObjRelease(hVfsObj);
     6239                if (RT_FAILURE(vrc))
     6240                    rc = setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to add '%s' to output (%Rrc)"), aFilename, vrc);
     6241            }
     6242            else
     6243                rc = setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("VDCreateVfsFileFromDisk failed for '%s' (%Rrc)"), aFilename, vrc);
     6244        }
     6245        catch (HRESULT hrc3) { rc = hrc3; }
     6246
     6247        VDDestroy(hdd);
     6248    }
     6249    catch (HRESULT hrc2) { rc = hrc2; }
     6250
     6251    /* Everything is explicitly unlocked when the task exits,
     6252     * as the task destruction also destroys the source chain. */
     6253
     6254    /* Make sure the source chain is released early, otherwise it can
     6255     * lead to deadlocks with concurrent IAppliance activities. */
     6256    SourceMediumLockList.Clear();
    60946257
    60956258    return rc;
Note: See TracChangeset for help on using the changeset viewer.

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