Changeset 47340 in vbox for trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
- Timestamp:
- Jul 23, 2013 12:27:35 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 87485
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r46980 r47340 119 119 { 120 120 // @todo: 121 // - don't use COM methods but the methods directly (faster, but needs appropriate locking of that objects itself (s. HardDisk)) 121 // - don't use COM methods but the methods directly (faster, but needs appropriate 122 // locking of that objects itself (s. HardDisk)) 122 123 // - Appropriate handle errors like not supported file formats 123 124 AutoCaller autoCaller(this); … … 280 281 if (cpuCountVBox > SchemaDefs::MaxCPUCount) 281 282 { 282 addWarning(tr("The virtual system \"%s\" claims support for %u CPU's, but VirtualBox has support for max %u CPU's only."), 283 addWarning(tr("The virtual system \"%s\" claims support for %u CPU's, but VirtualBox has support for " 284 "max %u CPU's only."), 283 285 vsysThis.strName.c_str(), cpuCountVBox, SchemaDefs::MaxCPUCount); 284 286 cpuCountVBox = SchemaDefs::MaxCPUCount; … … 306 308 ) 307 309 { 308 addWarning(tr("The virtual system \"%s\" claims support for %llu MB RAM size, but VirtualBox has support for min %u & max %u MB RAM size only."), 310 addWarning(tr("The virtual system \"%s\" claims support for %llu MB RAM size, but VirtualBox has " 311 "support for min %u & max %u MB RAM size only."), 309 312 vsysThis.strName.c_str(), ullMemSizeVBox, MM_RAM_MIN_IN_MB, MM_RAM_MAX_IN_MB); 310 313 ullMemSizeVBox = RT_MIN(RT_MAX(ullMemSizeVBox, MM_RAM_MIN_IN_MB), MM_RAM_MAX_IN_MB); … … 330 333 if ( vsysThis.pelmVboxMachine 331 334 && pNewDesc->m->pConfig->hardwareMachine.audioAdapter.fEnabled) 332 strSoundCard = Utf8StrFmt("%RU32", (uint32_t)pNewDesc->m->pConfig->hardwareMachine.audioAdapter.controllerType); 335 { 336 strSoundCard = Utf8StrFmt("%RU32", 337 (uint32_t)pNewDesc->m->pConfig->hardwareMachine.audioAdapter.controllerType); 338 } 333 339 else if (vsysThis.strSoundCardType.isNotEmpty()) 334 340 { … … 362 368 /* Check for the constrains */ 363 369 if (llNetworkAdapters.size() > maxNetworkAdapters) 364 addWarning(tr("The virtual system \"%s\" claims support for %zu network adapters, but VirtualBox has support for max %u network adapter only."), 370 addWarning(tr("The virtual system \"%s\" claims support for %zu network adapters, but VirtualBox " 371 "has support for max %u network adapter only."), 365 372 vsysThis.strName.c_str(), llNetworkAdapters.size(), maxNetworkAdapters); 366 373 /* Iterate through all network adapters. */ … … 390 397 /* Check for the constrains */ 391 398 if (cEthernetAdapters > maxNetworkAdapters) 392 addWarning(tr("The virtual system \"%s\" claims support for %zu network adapters, but VirtualBox has support for max %u network adapter only."), 399 addWarning(tr("The virtual system \"%s\" claims support for %zu network adapters, but VirtualBox " 400 "has support for max %u network adapter only."), 393 401 vsysThis.strName.c_str(), cEthernetAdapters, maxNetworkAdapters); 394 402 … … 534 542 /* Warn only once */ 535 543 if (cIDEused == 2) 536 addWarning(tr("The virtual \"%s\" system requests support for more than two IDE controller channels, but VirtualBox supports only two."), 544 addWarning(tr("The virtual \"%s\" system requests support for more than two " 545 "IDE controller channels, but VirtualBox supports only two."), 537 546 vsysThis.strName.c_str()); 538 547 … … 555 564 /* Warn only once */ 556 565 if (cSATAused == 1) 557 addWarning(tr("The virtual system \"%s\" requests support for more than one SATA controller, but VirtualBox has support for only one"), 566 addWarning(tr("The virtual system \"%s\" requests support for more than one " 567 "SATA controller, but VirtualBox has support for only one"), 558 568 vsysThis.strName.c_str()); 559 569 … … 582 592 } 583 593 else 584 addWarning(tr("The virtual system \"%s\" requests support for an additional SCSI controller of type \"%s\" with ID %s, but VirtualBox presently supports only one SCSI controller."), 594 addWarning(tr("The virtual system \"%s\" requests support for an additional " 595 "SCSI controller of type \"%s\" with ID %s, but VirtualBox presently " 596 "supports only one SCSI controller."), 585 597 vsysThis.strName.c_str(), 586 598 hdc.strControllerType.c_str(), … … 1276 1288 1277 1289 /* Next we have to download the OVF */ 1278 vrc = RTS3Create(&hS3, pTask->locInfo.strUsername.c_str(), pTask->locInfo.strPassword.c_str(), pTask->locInfo.strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING); 1290 vrc = RTS3Create(&hS3, 1291 pTask->locInfo.strUsername.c_str(), 1292 pTask->locInfo.strPassword.c_str(), 1293 pTask->locInfo.strHostname.c_str(), 1294 "virtualbox-agent/"VBOX_VERSION_STRING); 1279 1295 if (RT_FAILURE(vrc)) 1280 1296 throw setError(VBOX_E_IPRT_ERROR, … … 1291 1307 else if (vrc == VERR_S3_ACCESS_DENIED) 1292 1308 throw setError(E_ACCESSDENIED, 1293 tr("Cannot download file '%s' from S3 storage server (Access denied). Make sure that your credentials are right." 1309 tr("Cannot download file '%s' from S3 storage server (Access denied). Make sure that " 1310 "your credentials are right. " 1294 1311 "Also check that your host clock is properly synced"), 1295 1312 pszFilename); … … 1496 1513 PVDINTERFACEIO pFileIo = NULL; 1497 1514 void *pvMfBuf = NULL; 1515 void *pvCertBuf = NULL; 1498 1516 writeLock.release(); 1499 1517 try … … 1505 1523 1506 1524 Utf8Str strMfFile = Utf8Str(pTask->locInfo.strPath).stripExt().append(".mf"); 1525 1507 1526 SHASTORAGE storage; 1508 1527 RT_ZERO(storage); … … 1534 1553 /* Add the ovf file to the digest list. */ 1535 1554 stack.llSrcDisksDigest.push_front(STRPAIR(pTask->locInfo.strPath, m->strOVFSHADigest)); 1536 rc = read ManifestFile(strMfFile, &pvMfBuf, &cbMfSize, pShaIo, &storage);1555 rc = readFileToBuf(strMfFile, &pvMfBuf, &cbMfSize, true, pShaIo, &storage); 1537 1556 if (FAILED(rc)) throw rc; 1538 1557 rc = verifyManifestFile(strMfFile, stack, pvMfBuf, cbMfSize); 1539 1558 if (FAILED(rc)) throw rc; 1559 1560 size_t cbCertSize = 0; 1561 Utf8Str manifestShaDigest; 1562 Utf8Str strCertFile = Utf8Str(pTask->locInfo.strPath).stripExt().append(".cert"); 1563 if (RTFileExists(strCertFile.c_str())) 1564 { 1565 rc = readFileToBuf(strCertFile, &pvCertBuf, &cbCertSize, false, pShaIo, &storage); 1566 if (FAILED(rc)) throw rc; 1567 1568 /* Save the SHA digest of the manifest file for the next validation */ 1569 manifestShaDigest = storage.strDigest; 1570 1571 /* verify Certificate */ 1572 } 1540 1573 } 1541 1574 else … … 1554 1587 if (pvMfBuf) 1555 1588 RTMemFree(pvMfBuf); 1589 if (pvCertBuf) 1590 RTMemFree(pvCertBuf); 1556 1591 if (pShaIo) 1557 1592 RTMemFree(pShaIo); … … 1570 1605 1571 1606 RTTAR tar; 1572 int vrc = RTTarOpen(&tar, pTask->locInfo.strPath.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, true); 1607 int vrc = RTTarOpen(&tar, 1608 pTask->locInfo.strPath.c_str(), 1609 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, true); 1573 1610 if (RT_FAILURE(vrc)) 1574 1611 return setError(VBOX_E_FILE_ERROR, … … 1582 1619 char *pszFilename = 0; 1583 1620 void *pvMfBuf = 0; 1621 void *pvCertBuf = 0; 1622 1584 1623 writeLock.release(); 1585 1624 try … … 1629 1668 else 1630 1669 { 1670 RTTarCurrentFile(tar, &pszFilename); 1631 1671 if (vrc == VINF_TAR_DIR_PATH) 1632 1672 { 1633 RTTarCurrentFile(tar, &pszFilename);1634 1673 throw setError(VBOX_E_FILE_ERROR, 1635 1674 tr("Empty directory folder (%s) isn't allowed in the OVA package (%Rrc)"), … … 1662 1701 * If it fails here, we will try it again after all disks where read. 1663 1702 */ 1664 rc = readTar ManifestFile(tar, strMfFile, &pvMfBuf, &cbMfSize, pCallbacks, pStorage);1703 rc = readTarFileToBuf(tar, strMfFile, &pvMfBuf, &cbMfSize, true, pCallbacks, pStorage); 1665 1704 if (FAILED(rc)) throw rc; 1705 1706 /* 1707 * Try to read the certificate file. First try. 1708 * Logic is the same as with manifest file 1709 * Only if the manifest file had been read successfully before 1710 */ 1711 vrc = RTTarCurrentFile(tar, &pszFilename); 1712 if (RT_FAILURE(vrc)) 1713 throw setError(VBOX_E_IPRT_ERROR, 1714 tr("Getting the current file within the archive failed (%Rrc)"), vrc); 1715 1716 size_t cbCertSize = 0; 1717 Utf8Str strCertFile = Utf8Str(pszFilename).stripExt().append(".cert"); 1718 if (pvMfBuf) 1719 { 1720 if (strCertFile.compare(pszFilename) == 0) 1721 { 1722 rc = readTarFileToBuf(tar, strCertFile, &pvCertBuf, &cbCertSize, false, pCallbacks, pStorage); 1723 if (FAILED(rc)) throw rc; 1724 1725 if (pvCertBuf) 1726 { 1727 /* verify the certificate */ 1728 } 1729 } 1730 } 1731 1666 1732 /* Now import the appliance. */ 1667 1733 importMachines(stack, pCallbacks, pStorage); … … 1669 1735 if (!pvMfBuf) 1670 1736 { 1671 rc = readTar ManifestFile(tar, strMfFile, &pvMfBuf, &cbMfSize, pCallbacks, pStorage);1737 rc = readTarFileToBuf(tar, strMfFile, &pvMfBuf, &cbMfSize, true, pCallbacks, pStorage); 1672 1738 if (FAILED(rc)) throw rc; 1673 } 1674 /* If we were able to read a manifest file we can check it now. */ 1675 if (pvMfBuf) 1676 { 1677 /* Add the ovf file to the digest list. */ 1678 stack.llSrcDisksDigest.push_front(STRPAIR(Utf8Str(pszFilename).stripExt().append(".ovf"), m->strOVFSHADigest)); 1679 rc = verifyManifestFile(strMfFile, stack, pvMfBuf, cbMfSize); 1680 if (FAILED(rc)) throw rc; 1739 1740 /* If we were able to read a manifest file we can check it now. */ 1741 if (pvMfBuf) 1742 { 1743 /* Add the ovf file to the digest list. */ 1744 stack.llSrcDisksDigest.push_front(STRPAIR(Utf8Str(pszFilename).stripExt().append(".ovf"), 1745 m->strOVFSHADigest)); 1746 rc = verifyManifestFile(strMfFile, stack, pvMfBuf, cbMfSize); 1747 if (FAILED(rc)) throw rc; 1748 1749 /* 1750 * Try to read the certificate file. Second try. 1751 * Only if the manifest file had been read successfully before 1752 */ 1753 1754 vrc = RTTarCurrentFile(tar, &pszFilename); 1755 if (RT_FAILURE(vrc)) 1756 throw setError(VBOX_E_IPRT_ERROR, 1757 tr("Getting the current file within the archive failed (%Rrc)"), vrc); 1758 1759 if (strCertFile.compare(pszFilename) == 0) 1760 { 1761 rc = readTarFileToBuf(tar, strCertFile, &pvCertBuf, &cbCertSize, false, pCallbacks, pStorage); 1762 if (FAILED(rc)) throw rc; 1763 1764 if (pvCertBuf) 1765 { 1766 /* verify the certificate */ 1767 } 1768 } 1769 } 1681 1770 } 1682 1771 } … … 1698 1787 if (pTarIo) 1699 1788 RTMemFree(pTarIo); 1789 if (pvCertBuf) 1790 RTMemFree(pvCertBuf); 1700 1791 1701 1792 LogFlowFunc(("rc=%Rhrc\n", rc)); … … 1770 1861 1771 1862 /* Next we have to download the disk images */ 1772 vrc = RTS3Create(&hS3, pTask->locInfo.strUsername.c_str(), pTask->locInfo.strPassword.c_str(), pTask->locInfo.strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING); 1863 vrc = RTS3Create(&hS3, 1864 pTask->locInfo.strUsername.c_str(), 1865 pTask->locInfo.strPassword.c_str(), 1866 pTask->locInfo.strHostname.c_str(), 1867 "virtualbox-agent/"VBOX_VERSION_STRING); 1773 1868 if (RT_FAILURE(vrc)) 1774 1869 throw setError(VBOX_E_IPRT_ERROR, … … 1795 1890 throw setError(E_ACCESSDENIED, 1796 1891 tr("Cannot download file '%s' from S3 storage server (Access denied). " 1797 "Make sure that your credentials are right. Also check that your host clock is properly synced"), 1892 "Make sure that your credentials are right. Also check that your host clock is " 1893 "properly synced"), 1798 1894 pszFilename); 1799 1895 else if (vrc == VERR_S3_NOT_FOUND) … … 1831 1927 throw setError(E_ACCESSDENIED, 1832 1928 tr("Cannot download file '%s' from S3 storage server (Access denied)." 1833 "Make sure that your credentials are right. Also check that your host clock is properly synced"), 1929 "Make sure that your credentials are right. " 1930 "Also check that your host clock is properly synced"), 1834 1931 pszFilename); 1835 1932 else … … 1898 1995 #endif /* VBOX_WITH_S3 */ 1899 1996 1900 HRESULT Appliance::readManifestFile(const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage) 1997 HRESULT Appliance::readFileToBuf(const Utf8Str &strFile, 1998 void **ppvBuf, 1999 size_t *pcbSize, 2000 bool fCreateDigest, 2001 PVDINTERFACEIO pCallbacks, 2002 PSHASTORAGE pStorage) 1901 2003 { 1902 2004 HRESULT rc = S_OK; 1903 2005 1904 bool fOldDigest = pStorage->fCreateDigest; 1905 pStorage->fCreateDigest = f alse; /* No digest for the manifest file */2006 bool fOldDigest = pStorage->fCreateDigest;/* Save the old digest property */ 2007 pStorage->fCreateDigest = fCreateDigest; 1906 2008 int vrc = ShaReadBuf(strFile.c_str(), ppvBuf, pcbSize, pCallbacks, pStorage); 1907 2009 if ( RT_FAILURE(vrc) 1908 2010 && vrc != VERR_FILE_NOT_FOUND) 1909 2011 rc = setError(VBOX_E_FILE_ERROR, 1910 tr("Could not read manifestfile '%s' (%Rrc)"),2012 tr("Could not read file '%s' (%Rrc)"), 1911 2013 RTPathFilename(strFile.c_str()), vrc); 1912 2014 pStorage->fCreateDigest = fOldDigest; /* Restore the old digest creation behavior again. */ … … 1915 2017 } 1916 2018 1917 HRESULT Appliance::readTarManifestFile(RTTAR tar, const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage) 2019 HRESULT Appliance::readTarFileToBuf(RTTAR tar, 2020 const Utf8Str &strFile, 2021 void **ppvBuf, 2022 size_t *pcbSize, 2023 bool fCreateDigest, 2024 PVDINTERFACEIO pCallbacks, 2025 PSHASTORAGE pStorage) 1918 2026 { 1919 2027 HRESULT rc = S_OK; … … 1933 2041 { 1934 2042 if (!strcmp(pszCurFile, RTPathFilename(strFile.c_str()))) 1935 rc = read ManifestFile(strFile, ppvBuf, pcbSize, pCallbacks, pStorage);2043 rc = readFileToBuf(strFile, ppvBuf, pcbSize, fCreateDigest, pCallbacks, pStorage); 1936 2044 RTStrFree(pszCurFile); 1937 2045 } … … 1993 2101 int32_t &lDevice) 1994 2102 { 1995 Log(("Appliance::convertDiskAttachmentValues: hdc.system=%d, hdc.fPrimary=%d, ulAddressOnParent=%d\n", hdc.system, hdc.fPrimary, ulAddressOnParent)); 2103 Log(("Appliance::convertDiskAttachmentValues: hdc.system=%d, hdc.fPrimary=%d, ulAddressOnParent=%d\n", 2104 hdc.system, 2105 hdc.fPrimary, 2106 ulAddressOnParent)); 1996 2107 1997 2108 switch (hdc.system) … … 2089 2200 * 2090 2201 * @param di ovfreader.cpp structure describing the disk image from the OVF that is to be imported 2091 * @param ulSizeMB Size of the disk image (for progress reporting)2092 2202 * @param strTargetPath Where to create the target image. 2093 2203 * @param pTargetHD out: The newly created target disk. This also gets pushed on stack.llHardDisksCreated for cleanup. … … 2095 2205 */ 2096 2206 void Appliance::importOneDiskImage(const ovf::DiskImage &di, 2097 const Utf8Str &strTargetPath,2207 Utf8Str *strTargetPath, 2098 2208 ComObjPtr<Medium> &pTargetHD, 2099 2209 ImportStack &stack, … … 2101 2211 PSHASTORAGE pStorage) 2102 2212 { 2213 SHASTORAGE finalStorage; 2214 PSHASTORAGE pRealUsedStorage = pStorage;/* may be changed later to finalStorage */ 2215 PVDINTERFACEIO pFileIo = NULL;/* used in GZIP case*/ 2103 2216 ComObjPtr<Progress> pProgress; 2104 2217 pProgress.createObject(); 2105 HRESULT rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this), BstrFmt(tr("Creating medium '%s'"), strTargetPath.c_str()).raw(), TRUE); 2218 HRESULT rc = pProgress->init(mVirtualBox, 2219 static_cast<IAppliance*>(this), 2220 BstrFmt(tr("Creating medium '%s'"), 2221 strTargetPath->c_str()).raw(), 2222 TRUE); 2106 2223 if (FAILED(rc)) throw rc; 2107 2224 … … 2109 2226 SystemProperties *pSysProps = mVirtualBox->getSystemProperties(); 2110 2227 2228 /* 2229 * we put strSourceOVF into the stack.llSrcDisksDigest in the end of this 2230 * function like a key for a later validation of the SHA digests 2231 */ 2111 2232 const Utf8Str &strSourceOVF = di.strHref; 2112 2233 2113 2234 Utf8Str strSrcFilePath(stack.strSourceDir); 2235 Utf8Str strTargetDir(*strTargetPath); 2236 2114 2237 /* Construct source file path */ 2115 2238 Utf8Str name = applianceIOName(applianceIOTar); … … 2127 2250 * example. */ 2128 2251 RTUUID uuid; 2129 int vrc = RTUuidFromStr(&uuid, strTargetPath .c_str());2252 int vrc = RTUuidFromStr(&uuid, strTargetPath->c_str()); 2130 2253 if (vrc == VINF_SUCCESS) 2131 2254 { … … 2135 2258 else 2136 2259 { 2137 Utf8Str strTrgFormat = "VMDK"; 2138 ULONG lCabs = 0; 2139 2140 if (RTPathHaveExt(strTargetPath.c_str())) 2260 /* check read file to GZIP compression */ 2261 try 2141 2262 { 2142 char *pszExt = RTPathExt(strTargetPath.c_str()); 2143 /* Figure out which format the user like to have. Default is VMDK. */ 2144 ComObjPtr<MediumFormat> trgFormat = pSysProps->mediumFormatFromExtension(&pszExt[1]); 2145 if (trgFormat.isNull()) 2146 throw setError(VBOX_E_NOT_SUPPORTED, 2147 tr("Could not find a valid medium format for the target disk '%s'"), 2148 strTargetPath.c_str()); 2149 /* Check the capabilities. We need create capabilities. */ 2150 lCabs = 0; 2151 com::SafeArray <MediumFormatCapabilities_T> mediumFormatCap; 2152 rc = trgFormat->COMGETTER(Capabilities)(ComSafeArrayAsOutParam(mediumFormatCap)); 2153 2154 if (FAILED(rc)) throw rc; 2155 else 2156 { 2157 for (ULONG j = 0; j < mediumFormatCap.size(); j++) 2158 lCabs |= mediumFormatCap[j]; 2159 } 2160 2161 if (!( ((lCabs & MediumFormatCapabilities_CreateFixed) == MediumFormatCapabilities_CreateFixed) 2162 || ((lCabs & MediumFormatCapabilities_CreateDynamic) == MediumFormatCapabilities_CreateDynamic))) 2163 throw setError(VBOX_E_NOT_SUPPORTED, 2164 tr("Could not find a valid medium format for the target disk '%s'"), 2165 strTargetPath.c_str()); 2166 Bstr bstrFormatName; 2167 rc = trgFormat->COMGETTER(Name)(bstrFormatName.asOutParam()); 2168 if (FAILED(rc)) throw rc; 2169 strTrgFormat = Utf8Str(bstrFormatName); 2170 } 2171 2172 /* Create an IMedium object. */ 2173 pTargetHD.createObject(); 2174 2175 /*CD/DVD case*/ 2176 if (strTrgFormat.compare("RAW", Utf8Str::CaseInsensitive) == 0) 2177 { 2178 void *pvTmpBuf = 0; 2179 size_t cbSize = 0; 2180 2181 /* Read the ISO file into a memory buffer */ 2182 vrc = ShaReadBuf(strSrcFilePath.c_str(), &pvTmpBuf, &cbSize, pCallbacks, pStorage); 2183 2184 if ( RT_FAILURE(vrc) || !pvTmpBuf) 2185 throw setError(VBOX_E_FILE_ERROR, 2186 tr("Could not read ISO file '%s' (%Rrc)"), 2187 RTPathFilename(strSrcFilePath.c_str()), vrc); 2188 2189 if (RTFileExists(strTargetPath.c_str()) == false) 2190 { 2191 2192 /* ensure the directory exists */ 2193 if (lCabs & MediumFormatCapabilities_File) 2263 if (di.strCompression.compare("gzip",Utf8Str::CaseInsensitive) == 0) 2264 { 2265 /* 2266 * 1. extract a file to the local/temporary folder 2267 * 2. apply GZIP decompression for the file 2268 * 3. replace the value of strSrcFilePath with a new path to the file 2269 * 4. replace SHA-TAR I/O interface with File I/O interface 2270 * 5. save calculated SHA digest of GZIPed file for later validation 2271 */ 2272 2273 /* Decompress the GZIP file and save a new file in the target path */ 2274 strTargetDir = strTargetDir.stripFilename(); 2275 strTargetDir.append("/temp_"); 2276 2277 Utf8Str strTempTargetFilename(*strTargetPath); 2278 strTempTargetFilename = strTempTargetFilename.stripPath(); 2279 strTempTargetFilename = strTempTargetFilename.stripExt(); 2280 Utf8Str vdf = typeOfVirtualDiskFormatFromURI(di.strFormat); 2281 2282 strTargetDir.append(strTempTargetFilename); 2283 2284 vrc = decompressImageAndSave(strSrcFilePath.c_str(), strTargetDir.c_str(), pCallbacks, pStorage); 2285 2286 if (RT_FAILURE(vrc)) 2287 throw setError(VBOX_E_FILE_ERROR, 2288 tr("Could not read the file '%s' (%Rrc)"), 2289 RTPathFilename(strSrcFilePath.c_str()), vrc); 2290 2291 /* Create the necessary file access interfaces. */ 2292 pFileIo = FileCreateInterface(); 2293 if (!pFileIo) 2294 throw setError(E_OUTOFMEMORY); 2295 2296 name = applianceIOName(applianceIOFile); 2297 2298 vrc = VDInterfaceAdd(&pFileIo->Core, name.c_str(), 2299 VDINTERFACETYPE_IO, NULL, sizeof(VDINTERFACEIO), 2300 &finalStorage.pVDImageIfaces); 2301 if (RT_FAILURE(vrc)) 2302 throw setError(VBOX_E_IPRT_ERROR, 2303 tr("Creation of the VD interface failed (%Rrc)"), vrc); 2304 2305 strSrcFilePath = strTargetDir; 2306 strTargetDir = strTargetDir.stripFilename(); 2307 strTargetDir.append(RTPATH_SLASH_STR); 2308 strTargetDir.append(strTempTargetFilename.c_str()); 2309 *strTargetPath = strTargetDir.c_str(); 2310 2311 pRealUsedStorage = &finalStorage; 2312 } 2313 2314 Utf8Str strTrgFormat = "VMDK"; 2315 ULONG lCabs = 0; 2316 2317 if (RTPathHaveExt(strTargetPath->c_str())) 2318 { 2319 char *pszExt = RTPathExt(strTargetPath->c_str()); 2320 /* Figure out which format the user like to have. Default is VMDK. */ 2321 ComObjPtr<MediumFormat> trgFormat = pSysProps->mediumFormatFromExtension(&pszExt[1]); 2322 if (trgFormat.isNull()) 2323 throw setError(VBOX_E_NOT_SUPPORTED, 2324 tr("Could not find a valid medium format for the target disk '%s'"), 2325 strTargetPath->c_str()); 2326 /* Check the capabilities. We need create capabilities. */ 2327 lCabs = 0; 2328 com::SafeArray <MediumFormatCapabilities_T> mediumFormatCap; 2329 rc = trgFormat->COMGETTER(Capabilities)(ComSafeArrayAsOutParam(mediumFormatCap)); 2330 2331 if (FAILED(rc)) 2332 throw rc; 2333 else 2194 2334 { 2195 rc = VirtualBox::ensureFilePathExists(strTargetPath, true); 2196 if (FAILED(rc)) 2197 throw rc; 2335 for (ULONG j = 0; j < mediumFormatCap.size(); j++) 2336 lCabs |= mediumFormatCap[j]; 2198 2337 } 2199 2338 2200 // create a new file and copy raw data into one from buffer pvTmpBuf 2201 RTFILE pFile = NULL; 2202 vrc = RTFileOpen(&pFile, strTargetPath.c_str(), RTFILE_O_OPEN_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 2203 if (RT_SUCCESS(vrc) && pFile != NULL) 2339 if (!( ((lCabs & MediumFormatCapabilities_CreateFixed) == MediumFormatCapabilities_CreateFixed) 2340 || ((lCabs & MediumFormatCapabilities_CreateDynamic) == MediumFormatCapabilities_CreateDynamic))) 2341 throw setError(VBOX_E_NOT_SUPPORTED, 2342 tr("Could not find a valid medium format for the target disk '%s'"), 2343 strTargetPath->c_str()); 2344 Bstr bstrFormatName; 2345 rc = trgFormat->COMGETTER(Name)(bstrFormatName.asOutParam()); 2346 if (FAILED(rc)) throw rc; 2347 strTrgFormat = Utf8Str(bstrFormatName); 2348 } 2349 2350 /* Create an IMedium object. */ 2351 pTargetHD.createObject(); 2352 2353 /*CD/DVD case*/ 2354 if (strTrgFormat.compare("RAW", Utf8Str::CaseInsensitive) == 0) 2355 { 2356 void *pvTmpBuf = 0; 2357 size_t cbSize = 0; 2358 try 2204 2359 { 2205 size_t cbWritten = 0; 2206 2207 vrc = RTFileWrite(pFile, pvTmpBuf, cbSize, &cbWritten); 2208 2209 if (RT_FAILURE(vrc)) 2360 /* Read the ISO file into a memory buffer */ 2361 vrc = ShaReadBuf(strSrcFilePath.c_str(), &pvTmpBuf, &cbSize, pCallbacks, pRealUsedStorage); 2362 2363 if ( RT_FAILURE(vrc) || !pvTmpBuf) 2364 throw setError(VBOX_E_FILE_ERROR, 2365 tr("Could not read ISO file '%s' listed in the OVF file (%Rrc)"), 2366 RTPathFilename(strSourceOVF.c_str()), vrc); 2367 2368 if (RTFileExists(strTargetPath->c_str()) == false) 2210 2369 { 2211 Utf8Str path(strTargetPath); 2212 path = path.stripFilename(); 2213 if (pvTmpBuf) 2214 RTMemFree(pvTmpBuf); 2215 throw setError(VBOX_E_FILE_ERROR, 2216 tr("Could not write the ISO file '%s' into the folder %s (%Rrc)"), 2217 strSrcFilePath.stripPath().c_str(), 2218 path.c_str(), 2219 vrc); 2370 2371 /* ensure the directory exists */ 2372 if (lCabs & MediumFormatCapabilities_File) 2373 { 2374 rc = VirtualBox::ensureFilePathExists(*strTargetPath, true); 2375 if (FAILED(rc)) 2376 throw rc; 2377 } 2378 2379 // create a new file and copy raw data into one from buffer pvTmpBuf 2380 RTFILE pFile = NULL; 2381 vrc = RTFileOpen(&pFile, 2382 strTargetPath->c_str(), 2383 RTFILE_O_OPEN_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 2384 2385 if (RT_SUCCESS(vrc) && pFile != NULL) 2386 { 2387 size_t cbWritten = 0; 2388 2389 vrc = RTFileWrite(pFile, pvTmpBuf, cbSize, &cbWritten); 2390 2391 if (RT_FAILURE(vrc)) 2392 { 2393 Utf8Str path(*strTargetPath); 2394 path = path.stripFilename(); 2395 2396 throw setError(VBOX_E_FILE_ERROR, 2397 tr("Could not write the ISO file '%s' into the folder %s (%Rrc)"), 2398 strSrcFilePath.stripPath().c_str(), 2399 path.c_str(), 2400 vrc); 2401 } 2402 } 2403 RTFileClose(pFile); 2220 2404 } 2221 2405 } 2222 2223 RTFileClose(pFile); 2224 } 2225 /* Advance to the next operation. */ 2226 stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), 2227 RTPathFilename(strSrcFilePath.c_str())).raw(), 2228 di.ulSuggestedSizeMB);//operation's weight, as set up with the IProgress origi 2406 catch (HRESULT arc) 2407 { 2408 if (pvTmpBuf) 2409 RTMemFree(pvTmpBuf); 2410 throw; 2411 } 2412 2413 if (pvTmpBuf) 2414 RTMemFree(pvTmpBuf); 2415 2416 /* Advance to the next operation. */ 2417 /* operation's weight, as set up with the IProgress originally */ 2418 stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), 2419 RTPathFilename(strSourceOVF.c_str())).raw(), 2420 di.ulSuggestedSizeMB); 2421 } 2422 else/* HDD case*/ 2423 { 2424 rc = pTargetHD->init(mVirtualBox, 2425 strTrgFormat, 2426 *strTargetPath, 2427 Guid::Empty /* media registry: none yet */); 2428 if (FAILED(rc)) throw rc; 2429 2430 /* Now create an empty hard disk. */ 2431 rc = mVirtualBox->CreateHardDisk(Bstr(strTrgFormat).raw(), 2432 Bstr(*strTargetPath).raw(), 2433 ComPtr<IMedium>(pTargetHD).asOutParam()); 2434 if (FAILED(rc)) throw rc; 2435 2436 /* If strHref is empty we have to create a new file. */ 2437 if (strSourceOVF.isEmpty()) 2438 { 2439 com::SafeArray<MediumVariant_T> mediumVariant; 2440 mediumVariant.push_back(MediumVariant_Standard); 2441 /* Create a dynamic growing disk image with the given capacity. */ 2442 rc = pTargetHD->CreateBaseStorage(di.iCapacity / _1M, 2443 ComSafeArrayAsInParam(mediumVariant), 2444 ComPtr<IProgress>(pProgress).asOutParam()); 2445 if (FAILED(rc)) throw rc; 2446 2447 /* Advance to the next operation. */ 2448 /* operation's weight, as set up with the IProgress originally */ 2449 stack.pProgress->SetNextOperation(BstrFmt(tr("Creating disk image '%s'"), 2450 strTargetPath->c_str()).raw(), 2451 di.ulSuggestedSizeMB); 2452 } 2453 else 2454 { 2455 /* We need a proper source format description */ 2456 ComObjPtr<MediumFormat> srcFormat; 2457 /* Which format to use? */ 2458 Utf8Str strSrcFormat = "VDI"; 2459 2460 std::set<Utf8Str> listURIs = Appliance::URIFromTypeOfVirtualDiskFormat("VMDK"); 2461 std::set<Utf8Str>::const_iterator itr = listURIs.find(di.strFormat); 2462 2463 if (itr != listURIs.end()) 2464 { 2465 strSrcFormat = "VMDK"; 2466 } 2467 2468 srcFormat = pSysProps->mediumFormat(strSrcFormat); 2469 if (srcFormat.isNull()) 2470 throw setError(VBOX_E_NOT_SUPPORTED, 2471 tr("Could not find a valid medium format for the source disk '%s'"), 2472 RTPathFilename(strSourceOVF.c_str())); 2473 2474 /* Clone the source disk image */ 2475 ComObjPtr<Medium> nullParent; 2476 rc = pTargetHD->importFile(strSrcFilePath.c_str(), 2477 srcFormat, 2478 MediumVariant_Standard, 2479 pCallbacks, pRealUsedStorage, 2480 nullParent, 2481 pProgress); 2482 if (FAILED(rc)) throw rc; 2483 2484 /* Advance to the next operation. */ 2485 /* operation's weight, as set up with the IProgress originally */ 2486 stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), 2487 RTPathFilename(strSourceOVF.c_str())).raw(), 2488 di.ulSuggestedSizeMB); 2489 } 2490 2491 /* Now wait for the background disk operation to complete; this throws 2492 * HRESULTs on error. */ 2493 ComPtr<IProgress> pp(pProgress); 2494 waitForAsyncProgress(stack.pProgress, pp); 2495 } 2229 2496 } 2230 else/* HDD case*/2497 catch (...) 2231 2498 { 2232 rc = pTargetHD->init(mVirtualBox, 2233 strTrgFormat, 2234 strTargetPath, 2235 Guid::Empty /* media registry: none yet */); 2236 if (FAILED(rc)) throw rc; 2237 2238 /* Now create an empty hard disk. */ 2239 rc = mVirtualBox->CreateHardDisk(Bstr(strTrgFormat).raw(), 2240 Bstr(strTargetPath).raw(), 2241 ComPtr<IMedium>(pTargetHD).asOutParam()); 2242 if (FAILED(rc)) throw rc; 2243 2244 /* If strHref is empty we have to create a new file. */ 2245 if (strSourceOVF.isEmpty()) 2246 { 2247 com::SafeArray<MediumVariant_T> mediumVariant; 2248 mediumVariant.push_back(MediumVariant_Standard); 2249 /* Create a dynamic growing disk image with the given capacity. */ 2250 rc = pTargetHD->CreateBaseStorage(di.iCapacity / _1M, ComSafeArrayAsInParam(mediumVariant), ComPtr<IProgress>(pProgress).asOutParam()); 2251 if (FAILED(rc)) throw rc; 2252 2253 /* Advance to the next operation. */ 2254 stack.pProgress->SetNextOperation(BstrFmt(tr("Creating disk image '%s'"), strTargetPath.c_str()).raw(), 2255 di.ulSuggestedSizeMB); // operation's weight, as set up with the IProgress originally 2256 } 2257 else 2258 { 2259 /* We need a proper source format description */ 2260 ComObjPtr<MediumFormat> srcFormat; 2261 /* Which format to use? */ 2262 Utf8Str strSrcFormat = "VDI"; 2263 2264 std::set<Utf8Str> listURIs = Appliance::URIFromTypeOfVirtualDiskFormat("VMDK"); 2265 std::set<Utf8Str>::const_iterator itr = listURIs.find(di.strFormat); 2266 2267 if (itr != listURIs.end()) 2268 { 2269 strSrcFormat = "VMDK"; 2270 } 2271 2272 srcFormat = pSysProps->mediumFormat(strSrcFormat); 2273 if (srcFormat.isNull()) 2274 throw setError(VBOX_E_NOT_SUPPORTED, 2275 tr("Could not find a valid medium format for the source disk '%s'"), 2276 RTPathFilename(strSrcFilePath.c_str())); 2277 2278 /* Clone the source disk image */ 2279 ComObjPtr<Medium> nullParent; 2280 rc = pTargetHD->importFile(strSrcFilePath.c_str(), 2281 srcFormat, 2282 MediumVariant_Standard, 2283 pCallbacks, pStorage, 2284 nullParent, 2285 pProgress); 2286 if (FAILED(rc)) throw rc; 2287 2288 /* Advance to the next operation. */ 2289 stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), RTPathFilename(strSrcFilePath.c_str())).raw(), 2290 di.ulSuggestedSizeMB);// operation's weight, as set up with the IProgress originally); 2291 } 2292 2293 /* Now wait for the background disk operation to complete; this throws 2294 * HRESULTs on error. */ 2295 ComPtr<IProgress> pp(pProgress); 2296 waitForAsyncProgress(stack.pProgress, pp); 2499 if (pFileIo) 2500 RTMemFree(pFileIo); 2501 2502 throw; 2297 2503 } 2298 2504 } 2505 2506 if (pFileIo) 2507 RTMemFree(pFileIo); 2299 2508 2300 2509 /* Add the newly create disk path + a corresponding digest the our list for 2301 2510 * later manifest verification. */ 2302 stack.llSrcDisksDigest.push_back(STRPAIR(strS rcFilePath, pStorage ? pStorage->strDigest : ""));2511 stack.llSrcDisksDigest.push_back(STRPAIR(strSourceOVF, pStorage ? pStorage->strDigest : "")); 2303 2512 } 2304 2513 … … 2432 2641 else if (vsdeNW.size() > maxNetworkAdapters) 2433 2642 throw setError(VBOX_E_FILE_ERROR, 2434 tr("Too many network adapters: OVF requests %d network adapters, but VirtualBox only supports %d"), 2643 tr("Too many network adapters: OVF requests %d network adapters, " 2644 "but VirtualBox only supports %d"), 2435 2645 vsdeNW.size(), maxNetworkAdapters); 2436 2646 else … … 2540 2750 // IDE Hard disk controller 2541 2751 std::list<VirtualSystemDescriptionEntry*> vsdeHDCIDE = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskControllerIDE); 2542 // In OVF (at least VMware's version of it), an IDE controller has two ports, so VirtualBox's single IDE controller 2543 // with two channels and two ports each counts as two OVF IDE controllers -- so we accept one or two such IDE controllers 2752 /* 2753 * In OVF (at least VMware's version of it), an IDE controller has two ports, 2754 * so VirtualBox's single IDE controller with two channels and two ports each counts as 2755 * two OVF IDE controllers -- so we accept one or two such IDE controllers 2756 */ 2544 2757 size_t cIDEControllers = vsdeHDCIDE.size(); 2545 2758 if (cIDEControllers > 2) … … 2578 2791 if (hdcVBox == "AHCI") 2579 2792 { 2580 rc = pNewMachine->AddStorageController(Bstr("SATA Controller").raw(), StorageBus_SATA, pController.asOutParam()); 2793 rc = pNewMachine->AddStorageController(Bstr("SATA Controller").raw(), 2794 StorageBus_SATA, 2795 pController.asOutParam()); 2581 2796 if (FAILED(rc)) throw rc; 2582 2797 } … … 2629 2844 { 2630 2845 ComPtr<IStorageController> pController; 2631 rc = pNewMachine->AddStorageController(Bstr(L"SAS Controller").raw(), StorageBus_SAS, pController.asOutParam()); 2846 rc = pNewMachine->AddStorageController(Bstr(L"SAS Controller").raw(), 2847 StorageBus_SAS, 2848 pController.asOutParam()); 2632 2849 if (FAILED(rc)) throw rc; 2633 2850 rc = pController->COMSETTER(ControllerType)(StorageControllerType_LsiLogicSas); … … 2674 2891 { 2675 2892 ComPtr<IStorageController> pController; 2676 rc = sMachine->AddStorageController(Bstr("Floppy Controller").raw(), StorageBus_Floppy, pController.asOutParam()); 2893 rc = sMachine->AddStorageController(Bstr("Floppy Controller").raw(), 2894 StorageBus_Floppy, 2895 pController.asOutParam()); 2677 2896 if (FAILED(rc)) throw rc; 2678 2897 … … 2735 2954 while(oit != stack.mapDisks.end()) 2736 2955 { 2737 if (RTPathHaveExt(oit->second.strHref.c_str()))2738 {2739 /* Figure out which format the user have. */2740 char *pszExt = RTPathExt(oit->second.strHref.c_str());2741 /* Get the system properties. */2742 SystemProperties *pSysProps = mVirtualBox->getSystemProperties();2743 ComObjPtr<MediumFormat> trgFormat = pSysProps->mediumFormatFromExtension(&pszExt[1]);2744 if (trgFormat.isNull())2745 {2746 ++oit;2747 continue;2748 }2749 }2750 2751 2956 ovf::DiskImage diCurrent = oit->second; 2752 2957 ovf::VirtualDisksMap::const_iterator itVDisk = vsysThis.mapVirtualDisks.begin(); … … 2789 2994 2790 2995 /* 2791 *2792 2996 * preliminary check availability of the image 2793 2997 * This step is useful if image is placed in the OVA (TAR) package 2794 *2795 2998 */ 2796 2999 … … 2820 3023 { 2821 3024 /* 2822 *2823 3025 * availableImage contains the disk file reference (e.g. "disk1.vmdk"), which should exist 2824 3026 * in the global images map. … … 2847 3049 2848 3050 /* 2849 *2850 3051 * Again iterate over all given disk images of the virtual system 2851 3052 * disks description using the found disk image 2852 *2853 3053 */ 2854 3054 { … … 2901 3101 ComObjPtr<Medium> pTargetHD; 2902 3102 3103 Utf8Str savedVboxCurrent = vsdeTargetHD->strVboxCurrent; 3104 2903 3105 importOneDiskImage(diCurrent, 2904 vsdeTargetHD->strVboxCurrent,3106 &vsdeTargetHD->strVboxCurrent, 2905 3107 pTargetHD, 2906 3108 stack, … … 2965 3167 rc = sMachine->SaveSettings(); 2966 3168 if (FAILED(rc)) throw rc; 3169 3170 /* restore */ 3171 vsdeTargetHD->strVboxCurrent = savedVboxCurrent; 3172 2967 3173 } // end while(oit != stack.mapDisks.end()) 2968 3174 … … 3024 3230 3025 3231 /* 3026 *3027 3232 * step 1): modify machine config according to OVF config, in case the user 3028 3233 * has modified them using setFinalValues() 3029 *3030 3234 */ 3031 3235 … … 3168 3372 3169 3373 /* 3170 *3171 3374 * step 2: scan the machine config for media attachments 3172 *3173 3375 */ 3174 3376 … … 3187 3389 while(oit != stack.mapDisks.end()) 3188 3390 { 3189 if (RTPathHaveExt(oit->second.strHref.c_str()))3190 {3191 /* Figure out which format the user have. */3192 char *pszExt = RTPathExt(oit->second.strHref.c_str());3193 /* Get the system properties. */3194 SystemProperties *pSysProps = mVirtualBox->getSystemProperties();3195 ComObjPtr<MediumFormat> trgFormat = pSysProps->mediumFormatFromExtension(&pszExt[1]);3196 if (trgFormat.isNull())3197 {3198 ++oit;3199 continue;3200 }3201 }3202 3203 3391 ovf::DiskImage diCurrent = oit->second; 3204 3392 … … 3228 3416 3229 3417 /* 3230 *3231 3418 * preliminary check availability of the image 3232 3419 * This step is useful if image is placed in the OVA (TAR) package 3233 *3234 3420 */ 3235 3421 … … 3279 3465 diCurrent = *(&itDiskImage->second); 3280 3466 3281 /* Again iterate over all given disk images of the virtual system 3467 /* 3468 * Again iterate over all given disk images of the virtual system 3282 3469 * disks description using the found disk image 3283 3470 */ … … 3376 3563 continue; 3377 3564 } 3565 3378 3566 /* 3379 *3380 3567 * step 3: import disk 3381 *3382 3568 */ 3569 Utf8Str savedVboxCurrent = vsdeTargetHD->strVboxCurrent; 3383 3570 ComObjPtr<Medium> pTargetHD; 3384 3571 importOneDiskImage(diCurrent, 3385 vsdeTargetHD->strVboxCurrent,3572 &vsdeTargetHD->strVboxCurrent, 3386 3573 pTargetHD, 3387 3574 stack, … … 3418 3605 } 3419 3606 3607 /* restore */ 3608 vsdeTargetHD->strVboxCurrent = savedVboxCurrent; 3609 3420 3610 d.uuid = hdId; 3421 3611 fFound = true; … … 3434 3624 3435 3625 /* 3436 *3437 3626 * step 4): create the machine and have it import the config 3438 *3439 3627 */ 3440 3628 … … 3446 3634 // instance that we created from the vbox:Machine 3447 3635 rc = pNewMachine->init(mVirtualBox, 3448 stack.strNameVBox,// name from OVF preparations; can be suffixed to avoid duplicates , or changed by user3636 stack.strNameVBox,// name from OVF preparations; can be suffixed to avoid duplicates 3449 3637 config); // the whole machine config 3450 3638 if (FAILED(rc)) throw rc;
Note:
See TracChangeset
for help on using the changeset viewer.