Changeset 28162 in vbox for trunk/src/VBox/Main
- Timestamp:
- Apr 11, 2010 12:44:21 PM (15 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ApplianceImpl.cpp
r27918 r28162 628 628 } 629 629 630 void Appliance::disksWeight(uint32_t &ulTotalMB, uint32_t &cDisks) const 631 { 632 ulTotalMB = 0; 633 cDisks = 0; 634 /* Weigh the disk images according to their sizes */ 630 /** 631 * Refreshes the cDisks and ulTotalDisksMB members in the instance data. 632 * Requires that virtual system descriptions are present. 633 */ 634 void Appliance::disksWeight() 635 { 636 m->ulTotalDisksMB = 0; 637 m->cDisks = 0; 638 // weigh the disk images according to their sizes 635 639 list< ComObjPtr<VirtualSystemDescription> >::const_iterator it; 636 640 for (it = m->virtualSystemDescriptions.begin(); … … 647 651 { 648 652 const VirtualSystemDescriptionEntry *pHD = *itH; 649 ulTotalMB += pHD->ulSizeMB;650 ++ cDisks;653 m->ulTotalDisksMB += pHD->ulSizeMB; 654 ++m->cDisks; 651 655 } 652 656 } … … 654 658 } 655 659 656 HRESULT Appliance::setUpProgressFS(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription) 660 HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress, 661 const Bstr &bstrDescription, 662 SetUpProgressMode mode) 657 663 { 658 664 HRESULT rc; … … 661 667 pProgress.createObject(); 662 668 663 /* Weigh the disk images according to their sizes */ 664 uint32_t ulTotalMB; 665 uint32_t cDisks; 666 disksWeight(ulTotalMB, cDisks); 667 668 ULONG cOperations = 1 + cDisks; // one op per disk plus 1 for the XML 669 669 // compute the disks weight (this sets ulTotalDisksMB and cDisks in the instance data) 670 disksWeight(); 671 672 ULONG cOperations; 670 673 ULONG ulTotalOperationsWeight; 671 if (ulTotalMB) 672 { 673 m->ulWeightPerOperation = (ULONG)((double)ulTotalMB * 1 / 100); // use 1% of the progress for the XML 674 ulTotalOperationsWeight = ulTotalMB + m->ulWeightPerOperation; 674 675 cOperations = 1 // one for XML setup 676 + m->cDisks; // plus one per disk 677 if (m->ulTotalDisksMB) 678 { 679 m->ulWeightPerOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress for the XML 680 ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightPerOperation; 675 681 } 676 682 else 677 683 { 678 684 // no disks to export: 685 m->ulWeightPerOperation = 1; 679 686 ulTotalOperationsWeight = 1; 680 m->ulWeightPerOperation = 1; 687 } 688 689 switch (mode) 690 { 691 case Regular: 692 break; 693 694 case ImportS3: 695 { 696 cOperations += 1 + 1; // another one for the manifest file & another one for the import 697 ulTotalOperationsWeight = m->ulTotalDisksMB; 698 if (!m->ulTotalDisksMB) 699 // no disks to export: 700 ulTotalOperationsWeight = 1; 701 702 ULONG ulImportWeight = (ULONG)((double)ulTotalOperationsWeight * 50 / 100); // use 50% for import 703 ulTotalOperationsWeight += ulImportWeight; 704 705 m->ulWeightPerOperation = ulImportWeight; /* save for using later */ 706 707 ULONG ulInitWeight = (ULONG)((double)ulTotalOperationsWeight * 0.1 / 100); // use 0.1% for init 708 ulTotalOperationsWeight += ulInitWeight; 709 } 710 break; 711 712 case WriteS3: 713 { 714 cOperations += 1 + 1; // another one for the mf & another one for temporary creation 715 716 if (m->ulTotalDisksMB) 717 { 718 m->ulWeightPerOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress for OVF file upload (we didn't know the size at this point) 719 ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightPerOperation; 720 } 721 else 722 { 723 // no disks to export: 724 ulTotalOperationsWeight = 1; 725 m->ulWeightPerOperation = 1; 726 } 727 ULONG ulOVFCreationWeight = (ULONG)((double)ulTotalOperationsWeight * 50.0 / 100.0); /* Use 50% for the creation of the OVF & the disks */ 728 ulTotalOperationsWeight += ulOVFCreationWeight; 729 } 730 break; 681 731 } 682 732 683 733 Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightPerOperation = %d\n", 684 ulTotalMB,cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));734 m->ulTotalDisksMB, m->cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation)); 685 735 686 736 rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this), … … 691 741 bstrDescription, // CBSTR bstrFirstOperationDescription, 692 742 m->ulWeightPerOperation); // ULONG ulFirstOperationWeight, 693 return rc;694 }695 696 HRESULT Appliance::setUpProgressImportS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription)697 {698 HRESULT rc;699 700 /* Create the progress object */701 pProgress.createObject();702 703 /* Weigh the disk images according to their sizes */704 uint32_t ulTotalMB;705 uint32_t cDisks;706 disksWeight(ulTotalMB, cDisks);707 708 ULONG cOperations = 1 + 1 + 1 + cDisks; // one op per disk plus 1 for init, plus 1 for the manifest file & 1 plus for the import */709 710 ULONG ulTotalOperationsWeight = ulTotalMB;711 if (!ulTotalOperationsWeight)712 // no disks to export:713 ulTotalOperationsWeight = 1;714 715 ULONG ulImportWeight = (ULONG)((double)ulTotalOperationsWeight * 50 / 100); // use 50% for import716 ulTotalOperationsWeight += ulImportWeight;717 718 m->ulWeightPerOperation = ulImportWeight; /* save for using later */719 720 ULONG ulInitWeight = (ULONG)((double)ulTotalOperationsWeight * 0.1 / 100); // use 0.1% for init721 ulTotalOperationsWeight += ulInitWeight;722 723 Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightPerOperation = %d\n",724 ulTotalMB, cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));725 726 rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this),727 bstrDescription,728 TRUE /* aCancelable */,729 cOperations, // ULONG cOperations,730 ulTotalOperationsWeight, // ULONG ulTotalOperationsWeight,731 Bstr(tr("Init")), // CBSTR bstrFirstOperationDescription,732 ulInitWeight); // ULONG ulFirstOperationWeight,733 return rc;734 }735 736 HRESULT Appliance::setUpProgressWriteS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription)737 {738 HRESULT rc;739 740 /* Create the progress object */741 pProgress.createObject();742 743 /* Weigh the disk images according to their sizes */744 uint32_t ulTotalMB;745 uint32_t cDisks;746 disksWeight(ulTotalMB, cDisks);747 748 ULONG cOperations = 1 + 1 + 1 + cDisks; // one op per disk plus 1 for the OVF, plus 1 for the mf & 1 plus to the temporary creation */749 750 ULONG ulTotalOperationsWeight;751 if (ulTotalMB)752 {753 m->ulWeightPerOperation = (ULONG)((double)ulTotalMB * 1 / 100); // use 1% of the progress for OVF file upload (we didn't know the size at this point)754 ulTotalOperationsWeight = ulTotalMB + m->ulWeightPerOperation;755 }756 else757 {758 // no disks to export:759 ulTotalOperationsWeight = 1;760 m->ulWeightPerOperation = 1;761 }762 ULONG ulOVFCreationWeight = (ULONG)((double)ulTotalOperationsWeight * 50.0 / 100.0); /* Use 50% for the creation of the OVF & the disks */763 ulTotalOperationsWeight += ulOVFCreationWeight;764 765 Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightPerOperation = %d\n",766 ulTotalMB, cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));767 768 rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this),769 bstrDescription,770 TRUE /* aCancelable */,771 cOperations, // ULONG cOperations,772 ulTotalOperationsWeight, // ULONG ulTotalOperationsWeight,773 bstrDescription, // CBSTR bstrFirstOperationDescription,774 ulOVFCreationWeight); // ULONG ulFirstOperationWeight,775 743 return rc; 776 744 } -
trunk/src/VBox/Main/ApplianceImplExport.cpp
r28150 r28162 610 610 aLocInfo.strPath.c_str()); 611 611 612 /* todo: This progress init stuff should be done a little bit more generic */ 613 if (aLocInfo.storageType == VFSType_File) 614 rc = setUpProgressFS(aProgress, progressDesc); 615 else 616 rc = setUpProgressWriteS3(aProgress, progressDesc); 612 rc = setUpProgress(aProgress, progressDesc, (aLocInfo.storageType == VFSType_File) ? Regular : WriteS3); 617 613 618 614 /* Initialize our worker task */ -
trunk/src/VBox/Main/ApplianceImplImport.cpp
r28152 r28162 631 631 HRESULT Appliance::readImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress) 632 632 { 633 BstrFmt bstrDesc = BstrFmt(tr("Read appliance '%s'"),633 BstrFmt bstrDesc = BstrFmt(tr("Reading appliance '%s'"), 634 634 aLocInfo.strPath.c_str()); 635 635 HRESULT rc; … … 929 929 HRESULT Appliance::importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress) 930 930 { 931 Bstr progressDesc = BstrFmt(tr("Import appliance '%s'"),931 Bstr progressDesc = BstrFmt(tr("Importing appliance '%s'"), 932 932 aLocInfo.strPath.c_str()); 933 933 HRESULT rc = S_OK; 934 934 935 /* todo: This progress init stuff should be done a little bit more generic */ 936 if (aLocInfo.storageType == VFSType_File) 937 rc = setUpProgressFS(aProgress, progressDesc); 938 else 939 rc = setUpProgressImportS3(aProgress, progressDesc); 935 rc = setUpProgress(aProgress, 936 progressDesc, 937 (aLocInfo.storageType == VFSType_File) ? Regular : ImportS3); 940 938 if (FAILED(rc)) throw rc; 941 939 … … 960 958 // input pointers 961 959 const LocationInfo &locInfo; // ptr to location info from Appliance::importFS() 960 Utf8Str strSourceDir; // directory where source files reside 962 961 const ovf::DiskImagesMap &mapDisks; // ptr to disks map in OVF 963 962 ComObjPtr<Progress> &pProgress; // progress object passed into Appliance::importFS() … … 981 980 fSessionOpen(false) 982 981 { 982 // disk images have to be on the same place as the OVF file. So 983 // strip the filename out of the full file path 984 strSourceDir = aLocInfo.strPath; 985 strSourceDir.stripFilename(); 983 986 } 984 987 }; 985 988 986 989 /** 987 * Actual worker code for importing OVF data into VirtualBox. This is called from Appliance::taskThreadImportOrExport() 988 * and therefore runs on the OVF import worker thread. This runs in two contexts: 989 * 990 * 1) in a first worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(); 991 * 992 * 2) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which 993 * called Appliance::importS3(), which called Appliance::importImpl(), which then called this. 994 * 995 * @param pTask 990 * Checks if a manifest file exists in the given location and, if so, verifies 991 * that the relevant files (the OVF XML and the disks referenced by it, as 992 * represented by the VirtualSystemDescription instances contained in this appliance) 993 * match it. Requires a previous read() and interpret(). 994 * 995 * @param locInfo 996 * @param reader 996 997 * @return 997 998 */ 998 HRESULT Appliance:: importFS(const LocationInfo &locInfo,999 ComObjPtr<Progress> &pProgress)999 HRESULT Appliance::manifestVerify(const LocationInfo &locInfo, 1000 const ovf::OVFReader &reader) 1000 1001 { 1001 LogFlowFuncEnter();1002 LogFlowFunc(("Appliance %p\n", this));1003 1004 AutoCaller autoCaller(this);1005 if (FAILED(autoCaller.rc())) return autoCaller.rc();1006 1007 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);1008 1009 if (!isApplianceIdle())1010 return E_ACCESSDENIED;1011 1012 Assert(!pProgress.isNull());1013 1014 // Change the appliance state so we can safely leave the lock while doing time-consuming1015 // disk imports; also the below method calls do all kinds of locking which conflicts with1016 // the appliance object lock1017 m->state = Data::ApplianceImporting;1018 appLock.release();1019 1020 1002 HRESULT rc = S_OK; 1021 1003 1022 const ovf::OVFReader &reader = *m->pReader;1023 // this is safe to access because this thread only gets started1024 // if pReader != NULL1025 1026 // rollback for errors:1027 ImportStack stack(locInfo, reader.m_mapDisks, pProgress);1028 /* If a manifest file exists, verify the content. Therefore we need all1029 * files which are referenced by the OVF & the OVF itself */1030 1004 Utf8Str strMfFile = manifestFileName(locInfo.strPath); 1031 list<Utf8Str> filesList;1032 1005 if (RTPathExists(strMfFile.c_str())) 1033 1006 { 1007 list<Utf8Str> filesList; 1034 1008 Utf8Str strSrcDir(locInfo.strPath); 1035 1009 strSrcDir.stripFilename(); 1036 / * Add every disks of every virtual system to an internal list */1010 // add every disks of every virtual system to an internal list 1037 1011 list< ComObjPtr<VirtualSystemDescription> >::const_iterator it; 1038 1012 for (it = m->virtualSystemDescriptions.begin(); … … 1048 1022 { 1049 1023 VirtualSystemDescriptionEntry *vsdeHD = *itH; 1050 / * Find the disk from the OVF's disk list */1024 // find the disk from the OVF's disk list 1051 1025 ovf::DiskImagesMap::const_iterator itDiskImage = reader.m_mapDisks.find(vsdeHD->strRef); 1052 1026 const ovf::DiskImage &di = itDiskImage->second; … … 1055 1029 } 1056 1030 } 1057 /* Create the test list */ 1058 PRTMANIFESTTEST pTestList = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST)*(filesList.size()+1)); 1031 1032 // create the test list 1033 PRTMANIFESTTEST pTestList = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST) * (filesList.size() + 1)); 1059 1034 pTestList[0].pszTestFile = (char*)locInfo.strPath.c_str(); 1060 1035 pTestList[0].pszTestDigest = (char*)m->strOVFSHA1Digest.c_str(); … … 1071 1046 pTestList[i].pszTestDigest = pszDigest; 1072 1047 } 1048 1049 // this call can take a very long time 1073 1050 size_t cIndexOnError; 1074 vrc = RTManifestVerify(strMfFile.c_str(), pTestList, filesList.size() + 1, &cIndexOnError); 1075 if (vrc == VERR_MANIFEST_DIGEST_MISMATCH) 1076 rc = setError(VBOX_E_FILE_ERROR, 1077 tr("The SHA1 digest of '%s' doesn't match to the one in '%s'"), 1078 RTPathFilename(pTestList[cIndexOnError].pszTestFile), 1079 RTPathFilename(strMfFile.c_str())); 1080 else if (RT_FAILURE(vrc)) 1081 rc = setError(VBOX_E_FILE_ERROR, 1082 tr("Couldn't verify the content of '%s' against the available files (%Rrc)"), 1083 RTPathFilename(strMfFile.c_str()), 1084 vrc); 1085 /* Cleanup */ 1051 vrc = RTManifestVerify(strMfFile.c_str(), 1052 pTestList, 1053 filesList.size() + 1, 1054 &cIndexOnError); 1055 1056 // clean up 1086 1057 for (size_t j = 1; 1087 1058 j < filesList.size(); … … 1089 1060 RTStrFree(pTestList[j].pszTestDigest); 1090 1061 RTMemFree(pTestList); 1091 if (FAILED(rc)) return rc; 1092 } 1093 1094 rc = stack.pSession.createInprocObject(CLSID_Session); 1095 if (FAILED(rc)) return rc; 1096 1097 list<ovf::VirtualSystem>::const_iterator it; 1098 list< ComObjPtr<VirtualSystemDescription> >::const_iterator it1; 1099 /* Iterate through all virtual systems of that appliance */ 1100 size_t i = 0; 1101 for (it = reader.m_llVirtualSystems.begin(), 1102 it1 = m->virtualSystemDescriptions.begin(); 1103 it != reader.m_llVirtualSystems.end(); 1104 ++it, ++it1, ++i) 1105 { 1106 const ovf::VirtualSystem &vsysThis = *it; 1107 ComObjPtr<VirtualSystemDescription> vsdescThis = (*it1); 1108 1109 ComPtr<IMachine> pNewMachine; 1110 1111 /* Catch possible errors */ 1112 try 1062 1063 if (vrc == VERR_MANIFEST_DIGEST_MISMATCH) 1064 rc = setError(VBOX_E_FILE_ERROR, 1065 tr("The SHA1 digest of '%s' does not match the one in '%s'"), 1066 RTPathFilename(pTestList[cIndexOnError].pszTestFile), 1067 RTPathFilename(strMfFile.c_str())); 1068 else if (RT_FAILURE(vrc)) 1069 rc = setError(VBOX_E_FILE_ERROR, 1070 tr("Could not verify the content of '%s' against the available files (%Rrc)"), 1071 RTPathFilename(strMfFile.c_str()), 1072 vrc); 1073 } 1074 1075 return rc; 1076 } 1077 1078 /** 1079 * Actual worker code for importing OVF data into VirtualBox. This is called from Appliance::taskThreadImportOrExport() 1080 * and therefore runs on the OVF import worker thread. This runs in two contexts: 1081 * 1082 * 1) in a first worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(); 1083 * 1084 * 2) in a second worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl(), which 1085 * called Appliance::importS3(), which called Appliance::importImpl(), which then called this. 1086 * 1087 * @param pTask 1088 * @return 1089 */ 1090 HRESULT Appliance::importFS(const LocationInfo &locInfo, 1091 ComObjPtr<Progress> &pProgress) 1092 { 1093 LogFlowFuncEnter(); 1094 LogFlowFunc(("Appliance %p\n", this)); 1095 1096 AutoCaller autoCaller(this); 1097 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1098 1099 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS); 1100 1101 if (!isApplianceIdle()) 1102 return E_ACCESSDENIED; 1103 1104 Assert(!pProgress.isNull()); 1105 1106 // Change the appliance state so we can safely leave the lock while doing time-consuming 1107 // disk imports; also the below method calls do all kinds of locking which conflicts with 1108 // the appliance object lock 1109 m->state = Data::ApplianceImporting; 1110 appLock.release(); 1111 1112 HRESULT rc = S_OK; 1113 1114 const ovf::OVFReader &reader = *m->pReader; 1115 // this is safe to access because this thread only gets started 1116 // if pReader != NULL 1117 1118 // rollback for errors: 1119 ImportStack stack(locInfo, reader.m_mapDisks, pProgress); 1120 1121 try 1122 { 1123 // if a manifest file exists, verify the content; we then need all files which are referenced by the OVF & the OVF itself 1124 rc = manifestVerify(locInfo, reader); 1125 if (FAILED(rc)) throw rc; 1126 1127 // create a session for the machine + disks we manipulate below 1128 rc = stack.pSession.createInprocObject(CLSID_Session); 1129 if (FAILED(rc)) throw rc; 1130 1131 list<ovf::VirtualSystem>::const_iterator it; 1132 list< ComObjPtr<VirtualSystemDescription> >::const_iterator it1; 1133 /* Iterate through all virtual systems of that appliance */ 1134 size_t i = 0; 1135 for (it = reader.m_llVirtualSystems.begin(), 1136 it1 = m->virtualSystemDescriptions.begin(); 1137 it != reader.m_llVirtualSystems.end(); 1138 ++it, ++it1, ++i) 1113 1139 { 1140 const ovf::VirtualSystem &vsysThis = *it; 1141 ComObjPtr<VirtualSystemDescription> vsdescThis = (*it1); 1142 1143 ComPtr<IMachine> pNewMachine; 1144 1114 1145 // there are two ways in which we can create a vbox machine from OVF: 1115 1146 // -- either this OVF was written by vbox 3.2 or later, in which case there is a <vbox:Machine> element … … 1122 1153 1123 1154 if (vsdescThis->m->pConfig) 1124 importVBoxMachine(vs descThis, pNewMachine, stack);1155 importVBoxMachine(vsysThis, vsdescThis, pNewMachine, stack); 1125 1156 else 1126 1157 importMachineGeneric(vsysThis, vsdescThis, pNewMachine, stack); 1127 } 1128 catch (HRESULT aRC) 1129 { 1130 rc = aRC; 1131 } 1132 1133 if (FAILED(rc)) 1134 break; 1135 1136 } // for (it = pAppliance->m->llVirtualSystems.begin(), 1158 1159 } // for (it = pAppliance->m->llVirtualSystems.begin() ... 1160 } 1161 catch (HRESULT rc2) 1162 { 1163 rc = rc2; 1164 } 1137 1165 1138 1166 if (FAILED(rc)) … … 1199 1227 1200 1228 return rc; 1229 } 1230 1231 /** 1232 * 1233 * @param vsysThis OVF virtual system containing the VirtualDisksMap. We don't pass that directly 1234 * because it's a typedef which requires the whole ovfreader.h to be included otherwise. 1235 * @param vsdeHD 1236 * @param dstHdVBox 1237 * @param stack 1238 */ 1239 void Appliance::importOneDiskImage(const ovf::DiskImage &di, 1240 uint32_t ulSizeMB, 1241 const Utf8Str &strTargetPath, 1242 ComPtr<IMedium> &pTargetHD, 1243 ImportStack &stack) 1244 { 1245 ComPtr<IMedium> pSourceHD; 1246 bool fSourceHdNeedsClosing = false; 1247 1248 try 1249 { 1250 // destination file must not exist 1251 if ( strTargetPath.isEmpty() 1252 || RTPathExists(strTargetPath.c_str()) 1253 ) 1254 /* This isn't allowed */ 1255 throw setError(VBOX_E_FILE_ERROR, 1256 tr("Destination file '%s' exists"), 1257 strTargetPath.c_str()); 1258 1259 const Utf8Str &strSourceOVF = di.strHref; 1260 1261 // Make sure target directory exists 1262 HRESULT rc = VirtualBox::ensureFilePathExists(strTargetPath.c_str()); 1263 if (FAILED(rc)) 1264 throw rc; 1265 1266 // subprogress object for hard disk 1267 ComPtr<IProgress> pProgress2; 1268 1269 /* If strHref is empty we have to create a new file */ 1270 if (strSourceOVF.isEmpty()) 1271 { 1272 // which format to use? 1273 Bstr srcFormat = L"VDI"; 1274 if ( di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#sparse", Utf8Str::CaseInsensitive) 1275 || di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#compressed", Utf8Str::CaseInsensitive) 1276 ) 1277 srcFormat = L"VMDK"; 1278 // create an empty hard disk 1279 rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(strTargetPath), pTargetHD.asOutParam()); 1280 if (FAILED(rc)) throw rc; 1281 1282 // create a dynamic growing disk image with the given capacity 1283 rc = pTargetHD->CreateBaseStorage(di.iCapacity / _1M, MediumVariant_Standard, pProgress2.asOutParam()); 1284 if (FAILED(rc)) throw rc; 1285 1286 // advance to the next operation 1287 stack.pProgress->SetNextOperation(BstrFmt(tr("Creating virtual disk image '%s'"), strTargetPath.c_str()), 1288 ulSizeMB); // operation's weight, as set up with the IProgress originally 1289 } 1290 else 1291 { 1292 // construct source file path 1293 Utf8StrFmt strSrcFilePath("%s%c%s", stack.strSourceDir.c_str(), RTPATH_DELIMITER, strSourceOVF.c_str()); 1294 // source path must exist 1295 if (!RTPathExists(strSrcFilePath.c_str())) 1296 throw setError(VBOX_E_FILE_ERROR, 1297 tr("Source virtual disk image file '%s' doesn't exist"), 1298 strSrcFilePath.c_str()); 1299 1300 // Clone the disk image (this is necessary cause the id has 1301 // to be recreated for the case the same hard disk is 1302 // attached already from a previous import) 1303 1304 // First open the existing disk image 1305 rc = mVirtualBox->OpenHardDisk(Bstr(strSrcFilePath), 1306 AccessMode_ReadOnly, 1307 false, 1308 NULL, 1309 false, 1310 NULL, 1311 pSourceHD.asOutParam()); 1312 if (FAILED(rc)) throw rc; 1313 fSourceHdNeedsClosing = true; 1314 1315 /* We need the format description of the source disk image */ 1316 Bstr srcFormat; 1317 rc = pSourceHD->COMGETTER(Format)(srcFormat.asOutParam()); 1318 if (FAILED(rc)) throw rc; 1319 /* Create a new hard disk interface for the destination disk image */ 1320 rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(strTargetPath), pTargetHD.asOutParam()); 1321 if (FAILED(rc)) throw rc; 1322 /* Clone the source disk image */ 1323 rc = pSourceHD->CloneTo(pTargetHD, MediumVariant_Standard, NULL, pProgress2.asOutParam()); 1324 if (FAILED(rc)) throw rc; 1325 1326 /* Advance to the next operation */ 1327 stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), strSrcFilePath.c_str()), 1328 ulSizeMB); // operation's weight, as set up with the IProgress originally); 1329 } 1330 1331 // now wait for the background disk operation to complete; this throws HRESULTs on error 1332 waitForAsyncProgress(stack.pProgress, pProgress2); 1333 1334 if (fSourceHdNeedsClosing) 1335 { 1336 rc = pSourceHD->Close(); 1337 if (FAILED(rc)) throw rc; 1338 fSourceHdNeedsClosing = false; 1339 } 1340 1341 stack.llHardDisksCreated.push_back(pTargetHD); 1342 } 1343 catch (...) 1344 { 1345 if (fSourceHdNeedsClosing) 1346 pSourceHD->Close(); 1347 1348 throw; 1349 } 1201 1350 } 1202 1351 … … 1610 1759 { 1611 1760 pController = &kt->second; 1761 break; 1612 1762 } 1613 1763 } … … 1615 1765 if (!pController) 1616 1766 throw setError(VBOX_E_FILE_ERROR, 1617 1767 tr("OVF wants a CD-ROM drive but cannot find IDE controller, which is required in this version of VirtualBox")); 1618 1768 1619 1769 // this is for rollback later … … 1663 1813 // If there's an error here we need to close the session, so 1664 1814 // we need another try/catch block. 1665 ComPtr<IMedium> srcHdVBox;1666 bool fSourceHdNeedsClosing = false;1667 1668 1815 try 1669 1816 { … … 1673 1820 if (FAILED(rc)) throw rc; 1674 1821 stack.fSessionOpen = true; 1675 1676 /* The disk image has to be on the same place as the OVF file. So1677 * strip the filename out of the full file path. */1678 Utf8Str strSrcDir(stack.locInfo.strPath);1679 strSrcDir.stripFilename();1680 1822 1681 1823 /* Iterate over all given disk images */ … … 1687 1829 VirtualSystemDescriptionEntry *vsdeHD = *itHD; 1688 1830 1689 /* Check if the destination file exists already or the1690 * destination path is empty. */1691 if ( vsdeHD->strVbox.isEmpty()1692 || RTPathExists(vsdeHD->strVbox.c_str())1693 )1694 /* This isn't allowed */1695 throw setError(VBOX_E_FILE_ERROR,1696 tr("Destination file '%s' exists"),1697 vsdeHD->strVbox.c_str());1698 1699 /* Find the disk from the OVF's disk list */1700 ovf::DiskImagesMap::const_iterator itDiskImage = stack.mapDisks.find(vsdeHD->strRef);1701 1831 // vsdeHD->strRef contains the disk identifier (e.g. "vmdisk1"), which should exist 1702 1832 // in the virtual system's disks map under that ID and also in the global images map 1703 1833 ovf::VirtualDisksMap::const_iterator itVirtualDisk = vsysThis.mapVirtualDisks.find(vsdeHD->strRef); 1704 1705 if ( itDiskImage == stack.mapDisks.end() 1706 || itVirtualDisk == vsysThis.mapVirtualDisks.end() 1834 // and find the disk from the OVF's disk list 1835 ovf::DiskImagesMap::const_iterator itDiskImage = stack.mapDisks.find(vsdeHD->strRef); 1836 if ( (itVirtualDisk == vsysThis.mapVirtualDisks.end()) 1837 || (itDiskImage == stack.mapDisks.end()) 1707 1838 ) 1708 1839 throw setError(E_FAIL, … … 1712 1843 const ovf::VirtualDisk &vd = itVirtualDisk->second; 1713 1844 1714 /* Make sure all target directories exists */ 1715 rc = VirtualBox::ensureFilePathExists(vsdeHD->strVbox.c_str()); 1716 if (FAILED(rc)) 1717 throw rc; 1718 1719 // subprogress object for hard disk 1720 ComPtr<IProgress> pProgress2; 1721 1722 ComPtr<IMedium> dstHdVBox; 1723 /* If strHref is empty we have to create a new file */ 1724 if (di.strHref.isEmpty()) 1725 { 1726 /* Which format to use? */ 1727 Bstr srcFormat = L"VDI"; 1728 if ( di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#sparse", Utf8Str::CaseInsensitive) 1729 || di.strFormat.compare("http://www.vmware.com/specifications/vmdk.html#compressed", Utf8Str::CaseInsensitive)) 1730 srcFormat = L"VMDK"; 1731 /* Create an empty hard disk */ 1732 rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(vsdeHD->strVbox), dstHdVBox.asOutParam()); 1733 if (FAILED(rc)) throw rc; 1734 1735 /* Create a dynamic growing disk image with the given capacity */ 1736 rc = dstHdVBox->CreateBaseStorage(di.iCapacity / _1M, MediumVariant_Standard, pProgress2.asOutParam()); 1737 if (FAILED(rc)) throw rc; 1738 1739 /* Advance to the next operation */ 1740 stack.pProgress->SetNextOperation(BstrFmt(tr("Creating virtual disk image '%s'"), vsdeHD->strVbox.c_str()), 1741 vsdeHD->ulSizeMB); // operation's weight, as set up with the IProgress originally 1742 } 1743 else 1744 { 1745 /* Construct the source file path */ 1746 Utf8StrFmt strSrcFilePath("%s%c%s", strSrcDir.c_str(), RTPATH_DELIMITER, di.strHref.c_str()); 1747 /* Check if the source file exists */ 1748 if (!RTPathExists(strSrcFilePath.c_str())) 1749 /* This isn't allowed */ 1750 throw setError(VBOX_E_FILE_ERROR, 1751 tr("Source virtual disk image file '%s' doesn't exist"), 1752 strSrcFilePath.c_str()); 1753 1754 // Clone the disk image (this is necessary cause the id has 1755 // to be recreated for the case the same hard disk is 1756 // attached already from a previous import) 1757 1758 // First open the existing disk image 1759 rc = mVirtualBox->OpenHardDisk(Bstr(strSrcFilePath), 1760 AccessMode_ReadOnly, 1761 false, 1762 NULL, 1763 false, 1764 NULL, 1765 srcHdVBox.asOutParam()); 1766 if (FAILED(rc)) throw rc; 1767 fSourceHdNeedsClosing = true; 1768 1769 /* We need the format description of the source disk image */ 1770 Bstr srcFormat; 1771 rc = srcHdVBox->COMGETTER(Format)(srcFormat.asOutParam()); 1772 if (FAILED(rc)) throw rc; 1773 /* Create a new hard disk interface for the destination disk image */ 1774 rc = mVirtualBox->CreateHardDisk(srcFormat, Bstr(vsdeHD->strVbox), dstHdVBox.asOutParam()); 1775 if (FAILED(rc)) throw rc; 1776 /* Clone the source disk image */ 1777 rc = srcHdVBox->CloneTo(dstHdVBox, MediumVariant_Standard, NULL, pProgress2.asOutParam()); 1778 if (FAILED(rc)) throw rc; 1779 1780 /* Advance to the next operation */ 1781 stack.pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'"), strSrcFilePath.c_str()), 1782 vsdeHD->ulSizeMB); // operation's weight, as set up with the IProgress originally); 1783 } 1784 1785 // now wait for the background disk operation to complete; this throws HRESULTs on error 1786 waitForAsyncProgress(stack.pProgress, pProgress2); 1787 1788 if (fSourceHdNeedsClosing) 1789 { 1790 rc = srcHdVBox->Close(); 1791 if (FAILED(rc)) throw rc; 1792 fSourceHdNeedsClosing = false; 1793 } 1794 1795 stack.llHardDisksCreated.push_back(dstHdVBox); 1845 ComPtr<IMedium> pTargetHD; 1846 importOneDiskImage(di, 1847 vsdeHD->ulSizeMB, 1848 vsdeHD->strVbox, 1849 pTargetHD, 1850 stack); 1851 1796 1852 /* Now use the new uuid to attach the disk image to our new machine */ 1797 1853 ComPtr<IMachine> sMachine; … … 1799 1855 if (FAILED(rc)) throw rc; 1800 1856 Bstr hdId; 1801 rc = dstHdVBox->COMGETTER(Id)(hdId.asOutParam());1857 rc = pTargetHD->COMGETTER(Id)(hdId.asOutParam()); 1802 1858 if (FAILED(rc)) throw rc; 1803 1859 … … 1838 1894 catch(HRESULT /* aRC */) 1839 1895 { 1840 if (fSourceHdNeedsClosing)1841 srcHdVBox->Close();1842 1843 1896 if (stack.fSessionOpen) 1844 1897 stack.pSession->Close(); … … 1861 1914 * @param stack 1862 1915 */ 1863 void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis, 1916 void Appliance::importVBoxMachine(const ovf::VirtualSystem &vsysThis, 1917 ComObjPtr<VirtualSystemDescription> &vsdescThis, 1864 1918 ComPtr<IMachine> &pReturnNewMachine, 1865 1919 ImportStack &stack) -
trunk/src/VBox/Main/include/ApplianceImpl.h
r28110 r28162 31 31 class Progress; 32 32 class VirtualSystemDescription; 33 struct VirtualSystemDescriptionEntry; 33 34 34 35 namespace ovf … … 37 38 struct VirtualSystem; 38 39 class OVFReader; 40 struct DiskImage; 39 41 } 40 42 … … 120 122 void addWarning(const char* aWarning, ...); 121 123 122 void disksWeight(uint32_t &ulTotalMB, uint32_t &cDisks) const; 123 HRESULT setUpProgressFS(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription); 124 HRESULT setUpProgressImportS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription); 125 HRESULT setUpProgressWriteS3(ComObjPtr<Progress> &pProgress, const Bstr &bstrDescription); 124 void disksWeight(); 125 enum SetUpProgressMode { Regular, ImportS3, WriteS3 }; 126 HRESULT setUpProgress(ComObjPtr<Progress> &pProgress, 127 const Bstr &bstrDescription, 128 SetUpProgressMode mode); 126 129 127 130 struct LocationInfo; … … 145 148 146 149 HRESULT importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress); 150 HRESULT manifestVerify(const LocationInfo &locInfo, const ovf::OVFReader &reader); 147 151 148 152 HRESULT importFS(const LocationInfo &locInfo, ComObjPtr<Progress> &aProgress); 153 149 154 struct ImportStack; 150 void importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis, 151 ComPtr<IMachine> &pNewMachine, 152 ImportStack &stack); 155 void importOneDiskImage(const ovf::DiskImage &di, 156 uint32_t ulSizeMB, 157 const Utf8Str &strTargetPath, 158 ComPtr<IMedium> &pTargetHD, 159 ImportStack &stack); 153 160 void importMachineGeneric(const ovf::VirtualSystem &vsysThis, 154 161 ComObjPtr<VirtualSystemDescription> &vsdescThis, 155 162 ComPtr<IMachine> &pNewMachine, 156 163 ImportStack &stack); 164 void importVBoxMachine(const ovf::VirtualSystem &vsysThis, 165 ComObjPtr<VirtualSystemDescription> &vsdescThis, 166 ComPtr<IMachine> &pNewMachine, 167 ImportStack &stack); 168 157 169 HRESULT importS3(TaskOVF *pTask); 158 170 -
trunk/src/VBox/Main/include/ApplianceImplPrivate.h
r27976 r28162 80 80 81 81 ULONG ulWeightPerOperation; 82 ULONG ulTotalDisksMB; 83 ULONG cDisks; 82 84 Utf8Str strOVFSHA1Digest; 83 85 };
Note:
See TracChangeset
for help on using the changeset viewer.