Changeset 33417 in vbox
- Timestamp:
- Oct 25, 2010 12:32:50 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 10 edited
- 5 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/manual/en_US/SDKRef.xml
r33300 r33417 3499 3499 3500 3500 <listitem> 3501 <para><xref linkend="IMachine__export" 3502 xreflabel="IMachine::export()" /> received an extra parameter 3503 <computeroutput>location</computeroutput>, which is used to decide 3504 for the disk nameing.</para> 3505 </listitem> 3506 <listitem> 3501 3507 <para><xref linkend="IAppliance__write" 3502 3508 xreflabel="IAppliance::write()" /> received an extra parameter -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
r33406 r33417 927 927 CHECK_ERROR_BREAK(a->virtualBox, CreateAppliance(pAppliance.asOutParam())); 928 928 929 char *pszAbsFilePath = 0; 930 if (strOutputFile.startsWith("S3://", iprt::MiniString::CaseInsensitive) || 931 strOutputFile.startsWith("SunCloud://", iprt::MiniString::CaseInsensitive) || 932 strOutputFile.startsWith("webdav://", iprt::MiniString::CaseInsensitive)) 933 pszAbsFilePath = RTStrDup(strOutputFile.c_str()); 934 else 935 pszAbsFilePath = RTPathAbsDup(strOutputFile.c_str()); 936 929 937 std::list< ComPtr<IMachine> >::iterator itM; 930 938 uint32_t i=0; … … 935 943 ComPtr<IMachine> pMachine = *itM; 936 944 ComPtr<IVirtualSystemDescription> pVSD; 937 CHECK_ERROR_BREAK(pMachine, Export(pAppliance, pVSD.asOutParam()));945 CHECK_ERROR_BREAK(pMachine, Export(pAppliance, Bstr(pszAbsFilePath).raw(), pVSD.asOutParam())); 938 946 // Add additional info to the virtal system description if the user wants so 939 947 ArgsMap *pmapArgs = NULL; … … 1001 1009 1002 1010 ComPtr<IProgress> progress; 1003 char *pszAbsFilePath;1004 if (strOutputFile.startsWith("S3://", iprt::MiniString::CaseInsensitive) ||1005 strOutputFile.startsWith("SunCloud://", iprt::MiniString::CaseInsensitive) ||1006 strOutputFile.startsWith("webdav://", iprt::MiniString::CaseInsensitive))1007 pszAbsFilePath = RTStrDup(strOutputFile.c_str());1008 else1009 pszAbsFilePath = RTPathAbsDup(strOutputFile.c_str());1010 1011 CHECK_ERROR_BREAK(pAppliance, Write(Bstr(strOvfFormat).raw(), 1011 1012 fManifest, -
trunk/src/VBox/Frontends/VirtualBox/src/wizards/exportappliance/UIExportApplianceWzd.cpp
r33294 r33417 152 152 } 153 153 154 int UIExportApplianceWzdPage1::nextId() const 155 { 156 /* Skip next (3rd, storage-type) page for now! */ 157 return wizard()->page(QIWizardPage::nextId())->nextId(); 158 } 159 154 160 void UIExportApplianceWzdPage1::sltSelectedVMChanged() 155 161 { … … 204 210 /* Decorate page */ 205 211 Ui::UIExportApplianceWzdPage2::setupUi(this); 206 207 /* Register ExportAppliancePointer class */208 qRegisterMetaType<ExportAppliancePointer>();209 210 /* Register 'applianceWidget' field! */211 registerField("applianceWidget", this, "applianceWidget");212 m_pApplianceWidget = m_pSettingsCnt;213 }214 215 void UIExportApplianceWzdPage2::retranslateUi()216 {217 /* Translate uic generated strings */218 Ui::UIExportApplianceWzdPage2::retranslateUi(this);219 220 /* Wizard page 2 title */221 setTitle(tr("Appliance Export Settings"));222 }223 224 void UIExportApplianceWzdPage2::initializePage()225 {226 /* Fill and translate */227 retranslateUi();228 229 /* We propose a filename the first time the second page is displayed */230 prepareSettingsWidget();231 }232 233 void UIExportApplianceWzdPage2::cleanupPage()234 {235 /* Do NOT call superclass method, it will clean defailt (initially set) field - 'applianceWidget'! */236 }237 238 int UIExportApplianceWzdPage2::nextId() const239 {240 /* Skip next (3rd, storage-type) page for now! */241 return wizard()->page(QIWizardPage::nextId())->nextId();242 }243 244 bool UIExportApplianceWzdPage2::prepareSettingsWidget()245 {246 CVirtualBox vbox = vboxGlobal().virtualBox();247 CAppliance *appliance = m_pSettingsCnt->init();248 bool fResult = appliance->isOk();249 if (fResult)250 {251 /* Iterate over all the selected machine ids */252 QStringList uuids = field("machineIDs").toStringList();253 foreach (const QString &uuid, uuids)254 {255 /* Get the machine with the uuid */256 CMachine m = vbox.FindMachine(uuid);257 fResult = m.isOk();258 if (fResult)259 {260 /* Add the export description to our appliance object */261 CVirtualSystemDescription vsd = m.Export(*appliance);262 fResult = m.isOk();263 if (!fResult)264 {265 vboxProblem().cannotExportAppliance(m, appliance, this);266 return false;267 }268 /* Now add some new fields the user may change */269 vsd.AddDescription(KVirtualSystemDescriptionType_Product, "", "");270 vsd.AddDescription(KVirtualSystemDescriptionType_ProductUrl, "", "");271 vsd.AddDescription(KVirtualSystemDescriptionType_Vendor, "", "");272 vsd.AddDescription(KVirtualSystemDescriptionType_VendorUrl, "", "");273 vsd.AddDescription(KVirtualSystemDescriptionType_Version, "", "");274 vsd.AddDescription(KVirtualSystemDescriptionType_License, "", "");275 }276 else277 break;278 }279 /* Make sure the settings widget get the new descriptions */280 m_pSettingsCnt->populate();281 }282 if (!fResult)283 vboxProblem().cannotExportAppliance(appliance, this);284 return fResult;285 }286 287 UIExportApplianceWzdPage3::UIExportApplianceWzdPage3()288 {289 /* Decorate page */290 Ui::UIExportApplianceWzdPage3::setupUi(this);291 212 292 213 /* Register StorageType class */ … … 330 251 } 331 252 332 void UIExportApplianceWzdPage 3::retranslateUi()253 void UIExportApplianceWzdPage2::retranslateUi() 333 254 { 334 255 /* Translate uic generated strings */ 335 Ui::UIExportApplianceWzdPage 3::retranslateUi(this);256 Ui::UIExportApplianceWzdPage2::retranslateUi(this); 336 257 337 258 /* Wizard page 3 title */ … … 339 260 } 340 261 341 void UIExportApplianceWzdPage 3::initializePage()262 void UIExportApplianceWzdPage2::initializePage() 342 263 { 343 264 /* Fill and translate */ … … 348 269 } 349 270 350 void UIExportApplianceWzdPage 3::sltStorageTypeChanged()271 void UIExportApplianceWzdPage2::sltStorageTypeChanged() 351 272 { 352 273 /* Update selected storage-type */ … … 363 284 } 364 285 365 UIExportApplianceWzdPage 4::UIExportApplianceWzdPage4()286 UIExportApplianceWzdPage3::UIExportApplianceWzdPage3() 366 287 { 367 288 /* Decorate page */ 368 Ui::UIExportApplianceWzdPage 4::setupUi(this);289 Ui::UIExportApplianceWzdPage3::setupUi(this); 369 290 370 291 /* Configure the file selector */ … … 381 302 connect(m_pFileSelector, SIGNAL(pathChanged(const QString &)), this, SIGNAL(completeChanged())); 382 303 304 /* Register 'target' fields! */ 305 registerField("OVF09Selected", this, "OVF09Selected"); 306 registerField("manifestSelected", this, "manifestSelected"); 307 registerField("username", this, "username"); 308 registerField("password", this, "password"); 309 registerField("hostname", this, "hostname"); 310 registerField("bucket", this, "bucket"); 311 registerField("path", this, "path"); 312 383 313 #if 0 384 314 /* Load default attributes from GUI extra data */ … … 389 319 } 390 320 391 void UIExportApplianceWzdPage 4::retranslateUi()321 void UIExportApplianceWzdPage3::retranslateUi() 392 322 { 393 323 /* Translate uic generated strings */ 394 Ui::UIExportApplianceWzdPage 4::retranslateUi(this);324 Ui::UIExportApplianceWzdPage3::retranslateUi(this); 395 325 396 326 /* Wizard page 4 title */ … … 405 335 } 406 336 407 void UIExportApplianceWzdPage 4::initializePage()337 void UIExportApplianceWzdPage3::initializePage() 408 338 { 409 339 /* Fill and translate */ … … 489 419 } 490 420 491 bool UIExportApplianceWzdPage 4::isComplete() const421 bool UIExportApplianceWzdPage3::isComplete() const 492 422 { 493 423 const QString &strFile = m_pFileSelector->path().toLower(); … … 510 440 } 511 441 442 bool UIExportApplianceWzdPage3::validatePage() 443 { 444 return true; 445 // return exportAppliance(); 446 } 447 448 UIExportApplianceWzdPage4::UIExportApplianceWzdPage4() 449 { 450 /* Decorate page */ 451 Ui::UIExportApplianceWzdPage4::setupUi(this); 452 453 /* Register ExportAppliancePointer class */ 454 qRegisterMetaType<ExportAppliancePointer>(); 455 456 /* Register 'applianceWidget' field! */ 457 registerField("applianceWidget", this, "applianceWidget"); 458 m_pApplianceWidget = m_pSettingsCnt; 459 } 460 461 void UIExportApplianceWzdPage4::retranslateUi() 462 { 463 /* Translate uic generated strings */ 464 Ui::UIExportApplianceWzdPage4::retranslateUi(this); 465 466 /* Wizard page 2 title */ 467 setTitle(tr("Appliance Export Settings")); 468 } 469 470 void UIExportApplianceWzdPage4::initializePage() 471 { 472 /* Fill and translate */ 473 retranslateUi(); 474 475 /* We propose a filename the first time the second page is displayed */ 476 prepareSettingsWidget(); 477 } 478 479 void UIExportApplianceWzdPage4::cleanupPage() 480 { 481 /* Do NOT call superclass method, it will clean defailt (initially set) field - 'applianceWidget'! */ 482 } 483 512 484 bool UIExportApplianceWzdPage4::validatePage() 513 485 { 514 486 return exportAppliance(); 487 } 488 489 bool UIExportApplianceWzdPage4::prepareSettingsWidget() 490 { 491 CVirtualBox vbox = vboxGlobal().virtualBox(); 492 CAppliance *appliance = m_pSettingsCnt->init(); 493 bool fResult = appliance->isOk(); 494 if (fResult) 495 { 496 /* Iterate over all the selected machine ids */ 497 QStringList uuids = field("machineIDs").toStringList(); 498 foreach (const QString &uuid, uuids) 499 { 500 /* Get the machine with the uuid */ 501 CMachine m = vbox.FindMachine(uuid); 502 fResult = m.isOk(); 503 if (fResult) 504 { 505 /* Add the export description to our appliance object */ 506 CVirtualSystemDescription vsd = m.Export(*appliance, uri()); 507 fResult = m.isOk(); 508 if (!fResult) 509 { 510 vboxProblem().cannotExportAppliance(m, appliance, this); 511 return false; 512 } 513 /* Now add some new fields the user may change */ 514 vsd.AddDescription(KVirtualSystemDescriptionType_Product, "", ""); 515 vsd.AddDescription(KVirtualSystemDescriptionType_ProductUrl, "", ""); 516 vsd.AddDescription(KVirtualSystemDescriptionType_Vendor, "", ""); 517 vsd.AddDescription(KVirtualSystemDescriptionType_VendorUrl, "", ""); 518 vsd.AddDescription(KVirtualSystemDescriptionType_Version, "", ""); 519 vsd.AddDescription(KVirtualSystemDescriptionType_License, "", ""); 520 } 521 else 522 break; 523 } 524 /* Make sure the settings widget get the new descriptions */ 525 m_pSettingsCnt->populate(); 526 } 527 if (!fResult) 528 vboxProblem().cannotExportAppliance(appliance, this); 529 return fResult; 515 530 } 516 531 … … 525 540 * HardDiskImage. Also add the manifest file to the check. In the ova 526 541 * case only the target file itself get checked. */ 527 QFileInfo fi( m_pFileSelector->path());542 QFileInfo fi(field("path").toString()); 528 543 QVector<QString> files; 529 544 files << fi.fileName(); 530 545 if (fi.suffix().toLower() == "ovf") 531 546 { 532 if ( m_pSelectManifest->isChecked())547 if (field("manifestSelected").toBool()) 533 548 files << fi.baseName() + ".mf"; 534 549 CVirtualSystemDescriptionVector vsds = appliance->GetVirtualSystemDescriptions(); … … 600 615 { 601 616 /* Write the appliance */ 602 const QString version = m_pSelectOVF09->isChecked() ? "ovf-0.9" : "ovf-1.0";603 CProgress progress = appliance.Write(version, m_pSelectManifest->isChecked() /* fManifest */, uri());617 const QString version = field("OVF09Selected").toBool() ? "ovf-0.9" : "ovf-1.0"; 618 CProgress progress = appliance.Write(version, field("manifestSelected").toBool() /* fManifest */, uri()); 604 619 bool fResult = appliance.isOk(); 605 620 if (fResult) … … 629 644 case Filesystem: 630 645 { 631 return m_pFileSelector->path();646 return field("path").toString(); 632 647 } 633 648 case SunCloud: 634 649 { 635 650 QString uri("SunCloud://"); 636 if (! m_pLeUsername->text().isEmpty())637 uri = QString("%1%2").arg(uri).arg( m_pLeUsername->text());638 if (! m_pLePassword->text().isEmpty())639 uri = QString("%1:%2").arg(uri).arg( m_pLePassword->text());640 if (! m_pLeUsername->text().isEmpty() || !m_pLePassword->text().isEmpty())651 if (!field("username").toString().isEmpty()) 652 uri = QString("%1%2").arg(uri).arg(field("username").toString()); 653 if (!field("password").toString().isEmpty()) 654 uri = QString("%1:%2").arg(uri).arg(field("password").toString()); 655 if (!field("username").toString().isEmpty() || !field("username").toString().isEmpty()) 641 656 uri = QString("%1@").arg(uri); 642 uri = QString("%1%2/%3/%4").arg(uri).arg("object.storage.network.com").arg( m_pLeBucket->text()).arg(m_pFileSelector->path());657 uri = QString("%1%2/%3/%4").arg(uri).arg("object.storage.network.com").arg(field("bucket").toString()).arg(field("path").toString()); 643 658 return uri; 644 659 } … … 646 661 { 647 662 QString uri("S3://"); 648 if (! m_pLeUsername->text().isEmpty())649 uri = QString("%1%2").arg(uri).arg( m_pLeUsername->text());650 if (! m_pLePassword->text().isEmpty())651 uri = QString("%1:%2").arg(uri).arg( m_pLePassword->text());652 if (! m_pLeUsername->text().isEmpty() || !m_pLePassword->text().isEmpty())663 if (!field("username").toString().isEmpty()) 664 uri = QString("%1%2").arg(uri).arg(field("username").toString()); 665 if (!field("password").toString().isEmpty()) 666 uri = QString("%1:%2").arg(uri).arg(field("password").toString()); 667 if (!field("username").toString().isEmpty() || !field("password").toString().isEmpty()) 653 668 uri = QString("%1@").arg(uri); 654 uri = QString("%1%2/%3/%4").arg(uri).arg( m_pLeHostname->text()).arg(m_pLeBucket->text()).arg(m_pFileSelector->path());669 uri = QString("%1%2/%3/%4").arg(uri).arg(field("hostname").toString()).arg(field("bucket").toString()).arg(field("path").toString()); 655 670 return uri; 656 671 } -
trunk/src/VBox/Frontends/VirtualBox/src/wizards/exportappliance/UIExportApplianceWzd.h
r28800 r33417 78 78 bool isComplete() const; 79 79 80 int nextId() const; 81 80 82 private slots: 81 83 … … 102 104 { 103 105 Q_OBJECT; 106 Q_PROPERTY(StorageType storageType READ storageType WRITE setStorageType); 107 108 public: 109 110 UIExportApplianceWzdPage2(); 111 112 protected: 113 114 void retranslateUi(); 115 116 void initializePage(); 117 118 private slots: 119 120 void sltStorageTypeChanged(); 121 122 private: 123 124 StorageType storageType() const { return m_StorageType; } 125 void setStorageType(StorageType storageType) { m_StorageType = storageType; } 126 StorageType m_StorageType; 127 }; 128 129 class UIExportApplianceWzdPage3 : public QIWizardPage, public Ui::UIExportApplianceWzdPage3 130 { 131 Q_OBJECT; 132 133 Q_PROPERTY(bool OVF09Selected READ isOVF09Selected); 134 Q_PROPERTY(bool manifestSelected READ isManifestSelected); 135 Q_PROPERTY(QString username READ username); 136 Q_PROPERTY(QString password READ password); 137 Q_PROPERTY(QString hostname READ hostname); 138 Q_PROPERTY(QString bucket READ bucket); 139 Q_PROPERTY(QString path READ path); 140 141 public: 142 143 UIExportApplianceWzdPage3(); 144 145 protected: 146 147 void retranslateUi(); 148 149 void initializePage(); 150 151 bool isComplete() const; 152 bool validatePage(); 153 154 private: 155 156 bool isOVF09Selected() const { return m_pSelectOVF09->isChecked(); } 157 bool isManifestSelected() const { return m_pSelectManifest->isChecked(); } 158 QString username() const { return m_pLeUsername->text(); } 159 QString password() const { return m_pLePassword->text(); } 160 QString hostname() const { return m_pLeHostname->text(); } 161 QString bucket() const { return m_pLeBucket->text(); } 162 QString path() const { return m_pFileSelector->path(); } 163 164 QString m_strDefaultApplianceName; 165 }; 166 167 class UIExportApplianceWzdPage4 : public QIWizardPage, public Ui::UIExportApplianceWzdPage4 168 { 169 Q_OBJECT; 104 170 Q_PROPERTY(ExportAppliancePointer applianceWidget READ applianceWidget WRITE setApplianceWidget); 105 171 106 172 public: 107 173 108 UIExportApplianceWzdPage 2();174 UIExportApplianceWzdPage4(); 109 175 110 176 protected: … … 115 181 void cleanupPage(); 116 182 117 int nextId() const;183 bool validatePage(); 118 184 119 185 private: 120 186 121 187 bool prepareSettingsWidget(); 188 189 bool exportAppliance(); 190 bool exportVMs(CAppliance &appliance); 191 QString uri() const; 122 192 123 193 ExportAppliancePointer applianceWidget() const { return m_pApplianceWidget; } … … 126 196 }; 127 197 128 class UIExportApplianceWzdPage3 : public QIWizardPage, public Ui::UIExportApplianceWzdPage3129 {130 Q_OBJECT;131 Q_PROPERTY(StorageType storageType READ storageType WRITE setStorageType);132 133 public:134 135 UIExportApplianceWzdPage3();136 137 protected:138 139 void retranslateUi();140 141 void initializePage();142 143 private slots:144 145 void sltStorageTypeChanged();146 147 private:148 149 StorageType storageType() const { return m_StorageType; }150 void setStorageType(StorageType storageType) { m_StorageType = storageType; }151 StorageType m_StorageType;152 };153 154 class UIExportApplianceWzdPage4 : public QIWizardPage, public Ui::UIExportApplianceWzdPage4155 {156 Q_OBJECT;157 158 public:159 160 UIExportApplianceWzdPage4();161 162 protected:163 164 void retranslateUi();165 166 void initializePage();167 168 bool isComplete() const;169 bool validatePage();170 171 private:172 173 bool exportAppliance();174 bool exportVMs(CAppliance &appliance);175 QString uri() const;176 177 QString m_strDefaultApplianceName;178 };179 198 180 199 #endif /* __UIExportApplianceWzd_h__ */ -
trunk/src/VBox/Frontends/VirtualBox/src/wizards/exportappliance/UIExportApplianceWzdPage2.ui
r33404 r33417 14 14 hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 15 15 </comment> 16 <class>UIExportApplianceWzdPage 3</class>17 <widget class="QWidget" name="UIExportApplianceWzdPage 3">16 <class>UIExportApplianceWzdPage2</class> 17 <widget class="QWidget" name="UIExportApplianceWzdPage2"> 18 18 <property name="geometry"> 19 19 <rect> -
trunk/src/VBox/Frontends/VirtualBox/src/wizards/exportappliance/UIExportApplianceWzdPage3.ui
r33404 r33417 14 14 hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 15 15 </comment> 16 <class>UIExportApplianceWzdPage 4</class>17 <widget class="QWidget" name="UIExportApplianceWzdPage 4">16 <class>UIExportApplianceWzdPage3</class> 17 <widget class="QWidget" name="UIExportApplianceWzdPage3"> 18 18 <property name="geometry"> 19 19 <rect> -
trunk/src/VBox/Frontends/VirtualBox/src/wizards/exportappliance/UIExportApplianceWzdPage4.ui
r33404 r33417 14 14 hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 15 15 </comment> 16 <class>UIExportApplianceWzdPage 2</class>17 <widget class="QWidget" name="UIExportApplianceWzdPage 2">16 <class>UIExportApplianceWzdPage4</class> 17 <widget class="QWidget" name="UIExportApplianceWzdPage4"> 18 18 <property name="geometry"> 19 19 <rect> -
trunk/src/VBox/Main/ApplianceImpl.cpp
r33289 r33417 854 854 } 855 855 856 void Appliance::parseURI(Utf8Str strUri, LocationInfo &locInfo) const 856 void Appliance::parseBucket(Utf8Str &aPath, Utf8Str &aBucket) 857 { 858 /* Buckets are S3 specific. So parse the bucket out of the file path */ 859 if (!aPath.startsWith("/")) 860 throw setError(E_INVALIDARG, 861 tr("The path '%s' must start with /"), aPath.c_str()); 862 size_t bpos = aPath.find("/", 1); 863 if (bpos != Utf8Str::npos) 864 { 865 aBucket = aPath.substr(1, bpos - 1); /* The bucket without any slashes */ 866 aPath = aPath.substr(bpos); /* The rest of the file path */ 867 } 868 /* If there is no bucket name provided reject it */ 869 if (aBucket.isEmpty()) 870 throw setError(E_INVALIDARG, 871 tr("You doesn't provide a bucket name in the URI '%s'"), aPath.c_str()); 872 } 873 874 /** 875 * 876 * @return 877 */ 878 int Appliance::TaskOVF::startThread() 879 { 880 int vrc = RTThreadCreate(NULL, Appliance::taskThreadImportOrExport, this, 881 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0, 882 "Appliance::Task"); 883 884 if (RT_FAILURE(vrc)) 885 return Appliance::setErrorStatic(E_FAIL, 886 Utf8StrFmt("Could not create OVF task thread (%Rrc)\n", vrc)); 887 888 return S_OK; 889 } 890 891 /** 892 * Thread function for the thread started in Appliance::readImpl() and Appliance::importImpl() 893 * and Appliance::writeImpl(). 894 * This will in turn call Appliance::readFS() or Appliance::readS3() or Appliance::importFS() 895 * or Appliance::importS3() or Appliance::writeFS() or Appliance::writeS3(). 896 * 897 * @param aThread 898 * @param pvUser 899 */ 900 /* static */ 901 DECLCALLBACK(int) Appliance::taskThreadImportOrExport(RTTHREAD /* aThread */, void *pvUser) 902 { 903 std::auto_ptr<TaskOVF> task(static_cast<TaskOVF*>(pvUser)); 904 AssertReturn(task.get(), VERR_GENERAL_FAILURE); 905 906 Appliance *pAppliance = task->pAppliance; 907 908 LogFlowFuncEnter(); 909 LogFlowFunc(("Appliance %p\n", pAppliance)); 910 911 HRESULT taskrc = S_OK; 912 913 switch (task->taskType) 914 { 915 case TaskOVF::Read: 916 if (task->locInfo.storageType == VFSType_File) 917 taskrc = pAppliance->readFS(task.get()); 918 else if (task->locInfo.storageType == VFSType_S3) 919 taskrc = pAppliance->readS3(task.get()); 920 break; 921 922 case TaskOVF::Import: 923 if (task->locInfo.storageType == VFSType_File) 924 taskrc = pAppliance->importFS(task.get()); 925 else if (task->locInfo.storageType == VFSType_S3) 926 taskrc = pAppliance->importS3(task.get()); 927 break; 928 929 case TaskOVF::Write: 930 if (task->locInfo.storageType == VFSType_File) 931 taskrc = pAppliance->writeFS(task.get()); 932 else if (task->locInfo.storageType == VFSType_S3) 933 taskrc = pAppliance->writeS3(task.get()); 934 break; 935 } 936 937 task->rc = taskrc; 938 939 if (!task->pProgress.isNull()) 940 task->pProgress->notifyComplete(taskrc); 941 942 LogFlowFuncLeave(); 943 944 return VINF_SUCCESS; 945 } 946 947 /* static */ 948 int Appliance::TaskOVF::updateProgress(unsigned uPercent, void *pvUser) 949 { 950 Appliance::TaskOVF* pTask = *(Appliance::TaskOVF**)pvUser; 951 952 if ( pTask 953 && !pTask->pProgress.isNull()) 954 { 955 BOOL fCanceled; 956 pTask->pProgress->COMGETTER(Canceled)(&fCanceled); 957 if (fCanceled) 958 return -1; 959 pTask->pProgress->SetCurrentOperationProgress(uPercent); 960 } 961 return VINF_SUCCESS; 962 } 963 964 void parseURI(Utf8Str strUri, LocationInfo &locInfo) 857 965 { 858 966 /* Check the URI for the protocol */ … … 901 1009 } 902 1010 903 void Appliance::parseBucket(Utf8Str &aPath, Utf8Str &aBucket)904 {905 /* Buckets are S3 specific. So parse the bucket out of the file path */906 if (!aPath.startsWith("/"))907 throw setError(E_INVALIDARG,908 tr("The path '%s' must start with /"), aPath.c_str());909 size_t bpos = aPath.find("/", 1);910 if (bpos != Utf8Str::npos)911 {912 aBucket = aPath.substr(1, bpos - 1); /* The bucket without any slashes */913 aPath = aPath.substr(bpos); /* The rest of the file path */914 }915 /* If there is no bucket name provided reject it */916 if (aBucket.isEmpty())917 throw setError(E_INVALIDARG,918 tr("You doesn't provide a bucket name in the URI '%s'"), aPath.c_str());919 }920 921 /**922 *923 * @return924 */925 int Appliance::TaskOVF::startThread()926 {927 int vrc = RTThreadCreate(NULL, Appliance::taskThreadImportOrExport, this,928 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,929 "Appliance::Task");930 931 if (RT_FAILURE(vrc))932 return Appliance::setErrorStatic(E_FAIL,933 Utf8StrFmt("Could not create OVF task thread (%Rrc)\n", vrc));934 935 return S_OK;936 }937 938 /**939 * Thread function for the thread started in Appliance::readImpl() and Appliance::importImpl()940 * and Appliance::writeImpl().941 * This will in turn call Appliance::readFS() or Appliance::readS3() or Appliance::importFS()942 * or Appliance::importS3() or Appliance::writeFS() or Appliance::writeS3().943 *944 * @param aThread945 * @param pvUser946 */947 /* static */948 DECLCALLBACK(int) Appliance::taskThreadImportOrExport(RTTHREAD /* aThread */, void *pvUser)949 {950 std::auto_ptr<TaskOVF> task(static_cast<TaskOVF*>(pvUser));951 AssertReturn(task.get(), VERR_GENERAL_FAILURE);952 953 Appliance *pAppliance = task->pAppliance;954 955 LogFlowFuncEnter();956 LogFlowFunc(("Appliance %p\n", pAppliance));957 958 HRESULT taskrc = S_OK;959 960 switch (task->taskType)961 {962 case TaskOVF::Read:963 if (task->locInfo.storageType == VFSType_File)964 taskrc = pAppliance->readFS(task.get());965 else if (task->locInfo.storageType == VFSType_S3)966 taskrc = pAppliance->readS3(task.get());967 break;968 969 case TaskOVF::Import:970 if (task->locInfo.storageType == VFSType_File)971 taskrc = pAppliance->importFS(task.get());972 else if (task->locInfo.storageType == VFSType_S3)973 taskrc = pAppliance->importS3(task.get());974 break;975 976 case TaskOVF::Write:977 if (task->locInfo.storageType == VFSType_File)978 taskrc = pAppliance->writeFS(task.get());979 else if (task->locInfo.storageType == VFSType_S3)980 taskrc = pAppliance->writeS3(task.get());981 break;982 }983 984 task->rc = taskrc;985 986 if (!task->pProgress.isNull())987 task->pProgress->notifyComplete(taskrc);988 989 LogFlowFuncLeave();990 991 return VINF_SUCCESS;992 }993 994 /* static */995 int Appliance::TaskOVF::updateProgress(unsigned uPercent, void *pvUser)996 {997 Appliance::TaskOVF* pTask = *(Appliance::TaskOVF**)pvUser;998 999 if ( pTask1000 && !pTask->pProgress.isNull())1001 {1002 BOOL fCanceled;1003 pTask->pProgress->COMGETTER(Canceled)(&fCanceled);1004 if (fCanceled)1005 return -1;1006 pTask->pProgress->SetCurrentOperationProgress(uPercent);1007 }1008 return VINF_SUCCESS;1009 }1010 1011 1011 //////////////////////////////////////////////////////////////////////////////// 1012 1012 // -
trunk/src/VBox/Main/ApplianceImplExport.cpp
r33320 r33417 57 57 * @return 58 58 */ 59 60 STDMETHODIMP Machine::Export(IAppliance *aAppliance, IVirtualSystemDescription **aDescription) 59 STDMETHODIMP Machine::Export(IAppliance *aAppliance, IN_BSTR location, IVirtualSystemDescription **aDescription) 61 60 { 62 61 HRESULT rc = S_OK; … … 72 71 try 73 72 { 73 Appliance *pAppliance = static_cast<Appliance*>(aAppliance); 74 AutoCaller autoCaller1(pAppliance); 75 if (FAILED(autoCaller1.rc())) return autoCaller1.rc(); 76 77 LocationInfo locInfo; 78 parseURI(location, locInfo); 74 79 // create a new virtual system to store in the appliance 75 80 rc = pNewDesc.createObject(); … … 342 347 if (FAILED(rc)) throw rc; 343 348 344 strTargetVmdkName = bstrBaseName; 345 strTargetVmdkName.stripExt(); 346 strTargetVmdkName.append(".vmdk"); 349 Utf8Str strTargetName = Utf8Str(locInfo.strPath).stripPath().stripExt(); 350 strTargetVmdkName = Utf8StrFmt("%s-disk%d.vmdk", strTargetName.c_str(), ++pAppliance->m->cDisks); 347 351 348 352 // force reading state, or else size will be returned as 0 … … 521 525 Utf8StrFmt("%RI32", audioController)); 522 526 523 // finally, add the virtual system to the appliance524 Appliance *pAppliance = static_cast<Appliance*>(aAppliance);525 AutoCaller autoCaller1(pAppliance);526 if (FAILED(autoCaller1.rc())) return autoCaller1.rc();527 528 527 /* We return the new description to the caller */ 529 528 ComPtr<IVirtualSystemDescription> copy(pNewDesc); … … 531 530 532 531 AutoWriteLock alock(pAppliance COMMA_LOCKVAL_SRC_POS); 533 532 // finally, add the virtual system to the appliance 534 533 pAppliance->m->virtualSystemDescriptions.push_back(pNewDesc); 535 534 } -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r33386 r33417 3379 3379 <interface 3380 3380 name="IMachine" extends="$unknown" 3381 uuid=" 8934e426-1c09-459f-bbc4-58dba016fbbe"3381 uuid="cc4fec9a-3150-45df-9ee9-f00ba54d6ac3" 3382 3382 wsmap="managed" 3383 3383 > … … 5093 5093 <param name="aAppliance" type="IAppliance" dir="in"> 5094 5094 <desc>Appliance to export this machine to.</desc> 5095 </param> 5096 <param name="location" type="wstring" dir="in"> 5097 <desc>The target location.</desc> 5095 5098 </param> 5096 5099 <param name="aDescription" type="IVirtualSystemDescription" dir="return"> -
trunk/src/VBox/Main/include/ApplianceImpl.h
r33368 r33417 32 32 class VirtualSystemDescription; 33 33 struct VirtualSystemDescriptionEntry; 34 struct LocationInfo; 34 35 typedef struct VDINTERFACE *PVDINTERFACE; 35 36 typedef struct VDINTERFACEIO *PVDINTERFACEIO; … … 120 121 struct ImportStack; 121 122 struct TaskOVF; 122 struct LocationInfo;123 123 struct Data; // opaque, defined in ApplianceImpl.cpp 124 124 Data *m; … … 139 139 void addWarning(const char* aWarning, ...); 140 140 void disksWeight(); 141 void parseURI(Utf8Str strUri, LocationInfo &locInfo) const;142 141 void parseBucket(Utf8Str &aPath, Utf8Str &aBucket); 143 142 … … 223 222 }; 224 223 224 void parseURI(Utf8Str strUri, LocationInfo &locInfo); 225 225 226 struct VirtualSystemDescriptionEntry 226 227 { -
trunk/src/VBox/Main/include/ApplianceImplPrivate.h
r33289 r33417 33 33 /* Describe a location for the import/export. The location could be a file on a 34 34 * local hard disk or a remote target based on the supported inet protocols. */ 35 struct Appliance::LocationInfo35 struct LocationInfo 36 36 { 37 37 LocationInfo() … … 53 53 , fManifest(true) 54 54 , pReader(NULL) 55 , ulWeightForXmlOperation(0) 56 , ulWeightForManifestOperation(0) 57 , ulTotalDisksMB(0) 58 , cDisks(0) 55 59 { 56 60 } -
trunk/src/VBox/Main/include/MachineImpl.h
r33386 r33417 490 490 STDMETHOD(Unregister)(CleanupMode_T cleanupMode, ComSafeArrayOut(IMedium*, aMedia)); 491 491 STDMETHOD(Delete)(ComSafeArrayIn(IMedium*, aMedia), IProgress **aProgress); 492 STDMETHOD(Export)(IAppliance *aAppliance, I VirtualSystemDescription **aDescription);492 STDMETHOD(Export)(IAppliance *aAppliance, IN_BSTR location, IVirtualSystemDescription **aDescription); 493 493 STDMETHOD(FindSnapshot)(IN_BSTR aNameOrId, ISnapshot **aSnapshot); 494 494 STDMETHOD(CreateSharedFolder)(IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable, BOOL aAutoMount);
Note:
See TracChangeset
for help on using the changeset viewer.