Changeset 73892 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- Aug 26, 2018 3:30:15 PM (6 years ago)
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/ApplianceImpl.cpp
r73743 r73892 1214 1214 } 1215 1215 1216 /** 1217 * Worker for TaskOPC::handler. 1218 * @thread pTask The task. 1219 */ 1220 /* static */ 1221 void 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 */ 1248 DECLCALLBACK(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 */ 1269 void 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 */ 1296 DECLCALLBACK(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 1216 1312 void i_parseURI(Utf8Str strUri, LocationInfo &locInfo) 1217 1313 { … … 1231 1327 locInfo.storageType = VFSType_S3; 1232 1328 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); 1233 1334 } 1234 1335 else if (strUri.startsWith("webdav://", Utf8Str::CaseInsensitive)) /* webdav service */ … … 1491 1592 vsde.strRef = strRef; 1492 1593 vsde.strOvf = aOvfValue; 1493 vsde.strVBoxSuggested / / remember original value1494 = 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() */ 1495 1596 = aVBoxValue; 1496 1597 vsde.strExtraConfigSuggested -
trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp
r73505 r73892 645 645 } 646 646 647 HRESULT rc = S_OK; 647 648 // AssertReturn(!(m->optListExport.contains(ExportOptions_CreateManifest) 648 649 // && m->optListExport.contains(ExportOptions_ExportDVDImages)), E_INVALIDARG); 649 650 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 } 684 688 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 692 725 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 } 727 778 728 779 return rc; … … 792 843 } 793 844 845 846 HRESULT 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 922 HRESULT 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 794 957 /** 795 958 * Called from Appliance::i_writeFS() for creating a XML document for this … … 986 1149 // output filename 987 1150 const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf; 1151 988 1152 // target path needs to be composed from where the output OVF is 989 1153 Utf8Str strTargetFilePath(strPath); … … 1982 2146 m->state = Data::ApplianceExporting; 1983 2147 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)) 1987 2149 rc = i_writeFSOVF(pTask, multiLock); 1988 2150 else … … 2088 2250 2089 2251 /** 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 */ 2256 HRESULT Appliance::i_writeFSOCI(TaskOCI *pTask) 2257 { 2258 LogFlowFuncEnter(); 2259 HRESULT hrc = S_OK; 2260 2261 return hrc; 2262 } 2263 2264 /** 2090 2265 * Writes the Oracle Public Cloud appliance. 2091 2266 * … … 2093 2268 * to save diskspace on the target host system. 2094 2269 */ 2095 HRESULT Appliance::i_writeFSOPC(TaskO VF *pTask, AutoWriteLockBase &writeLock)2270 HRESULT Appliance::i_writeFSOPC(TaskOPC *pTask) 2096 2271 { 2097 2272 LogFlowFuncEnter(); 2098 2273 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; 2099 2282 2100 2283 /* … … 2110 2293 { 2111 2294 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); 2113 2296 } 2114 2297 … … 2169 2352 if (cTarballs > 0) 2170 2353 { 2171 2172 2354 strTarballPath.stripFilename().append(RTPATH_SLASH_STR).append(pDiskEntry->strOvf); 2173 2355 const char *pszExt = RTPathSuffix(pDiskEntry->strOvf.c_str()); … … 2216 2398 * leave the appliance lock. 2217 2399 */ 2218 writeLock.release();2400 multiLock.release(); 2219 2401 2220 2402 pTask->pProgress->SetNextOperation(BstrFmt(tr("Exporting to disk image '%Rbn'"), strTarballPath.c_str()).raw(), … … 2224 2406 pTask->pProgress, true /*fSparse*/); 2225 2407 2226 writeLock.acquire();2408 multiLock.acquire(); 2227 2409 if (SUCCEEDED(hrc)) 2228 2410 { … … 2268 2450 RTFileDelete(it->c_str()); 2269 2451 2452 // reset the state so others can call methods again 2453 m->state = Data::ApplianceIdle; 2454 2270 2455 LogFlowFuncLeave(); 2271 2456 return hrc; … … 2380 2565 // output filename 2381 2566 const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf; 2567 2382 2568 // target path needs to be composed from where the output OVF is 2383 2569 const Utf8Str &strTargetFilePath = strTargetFileNameOnly;
Note:
See TracChangeset
for help on using the changeset viewer.