Changeset 67203 in vbox for trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp
- Timestamp:
- Jun 1, 2017 11:50:09 AM (8 years ago)
- File:
-
- 1 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();
Note:
See TracChangeset
for help on using the changeset viewer.