Changeset 67203 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- Jun 1, 2017 11:50:09 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 115885
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp
r67197 r67203 2206 2206 { 2207 2207 LogFlowFuncEnter(); 2208 HRESULT hrc = S_OK; 2208 2209 2209 2210 /* 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. 2211 2213 */ 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); 2228 2309 RTVfsIoStrmRelease(hVfsIosGzip); 2229 if (RT_SUCCESS(vrc)) 2310 2311 if (RT_FAILURE(vrc)) 2230 2312 { 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 2231 2363 /* 2232 * Before we do the actual writing, disable OVF and manifest creation.2364 * Complete and close the tarball. 2233 2365 */ 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); 2238 2367 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; } 2241 2376 } 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()); 2254 2401 2255 2402 LogFlowFuncLeave(); -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r67184 r67203 6092 6092 } 6093 6093 catch (HRESULT aRC) { rc = aRC; } 6094 6095 return rc; 6096 } 6097 6098 /** 6099 * 6100 * @note Similar code exists in i_taskExportHandler. 6101 */ 6102 HRESULT 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(); 6094 6257 6095 6258 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.