Changeset 78428 in vbox for trunk/src/VBox
- Timestamp:
- May 7, 2019 11:03:49 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 130427
- Location:
- trunk/src/VBox
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
r76553 r78428 146 146 { "--disk", 'D', RTGETOPT_REQ_STRING }, 147 147 { "--options", 'O', RTGETOPT_REQ_STRING }, 148 149 { "--cloud", 'j', RTGETOPT_REQ_NOTHING}, 150 { "--cloudprofile", 'k', RTGETOPT_REQ_STRING }, 151 { "--cloudinstanceid", 'l', RTGETOPT_REQ_STRING } 148 152 }; 153 154 enum 155 { 156 NOT_SET, LOCAL, CLOUD 157 } actionType; 149 158 150 159 RTEXITCODE handleImportAppliance(HandlerArg *arg) 151 160 { 152 161 HRESULT rc = S_OK; 153 162 bool fCloud = false; // the default 163 actionType = NOT_SET; 154 164 Utf8Str strOvfFilename; 155 165 bool fExecute = true; // if true, then we actually do the import … … 182 192 183 193 case 's': // --vsys 194 if (fCloud == false && actionType == NOT_SET) 195 actionType = LOCAL; 196 197 if (actionType != LOCAL) 198 return errorSyntax(USAGE_EXPORTAPPLIANCE, 199 "Option \"%s\" can't be used together with \"--cloud\" argument.", 200 GetState.pDef->pszLong); 201 184 202 ulCurVsys = ValueUnion.u32; 185 203 ulCurUnit = (uint32_t)-1; … … 187 205 188 206 case 'o': // --ostype 189 if ( ulCurVsys == (uint32_t)-1)190 return errorSyntax(USAGE_ IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);207 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 208 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 191 209 mapArgsMapsPerVsys[ulCurVsys]["ostype"] = ValueUnion.psz; 192 210 break; 193 211 194 212 case 'V': // --vmname 195 if ( ulCurVsys == (uint32_t)-1)213 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 196 214 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 197 215 mapArgsMapsPerVsys[ulCurVsys]["vmname"] = ValueUnion.psz; … … 199 217 200 218 case 'S': // --settingsfile 201 if ( ulCurVsys == (uint32_t)-1)219 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 202 220 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 203 221 mapArgsMapsPerVsys[ulCurVsys]["settingsfile"] = ValueUnion.psz; … … 205 223 206 224 case 'p': // --basefolder 207 if ( ulCurVsys == (uint32_t)-1)225 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 208 226 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 209 227 mapArgsMapsPerVsys[ulCurVsys]["basefolder"] = ValueUnion.psz; … … 211 229 212 230 case 'g': // --group 213 if ( ulCurVsys == (uint32_t)-1)231 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 214 232 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 215 233 mapArgsMapsPerVsys[ulCurVsys]["group"] = ValueUnion.psz; … … 217 235 218 236 case 'd': // --description 219 if ( ulCurVsys == (uint32_t)-1)237 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 220 238 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 221 239 mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz; … … 223 241 224 242 case 'L': // --eula 225 if ( ulCurVsys == (uint32_t)-1)243 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 226 244 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 227 245 mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz; … … 229 247 230 248 case 'm': // --memory 231 if ( ulCurVsys == (uint32_t)-1)249 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 232 250 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 233 251 mapArgsMapsPerVsys[ulCurVsys]["memory"] = ValueUnion.psz; … … 235 253 236 254 case 'c': // --cpus 237 if ( ulCurVsys == (uint32_t)-1)255 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 238 256 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 239 257 mapArgsMapsPerVsys[ulCurVsys]["cpus"] = ValueUnion.psz; … … 245 263 246 264 case 'x': // --ignore 247 if ( ulCurVsys == (uint32_t)-1)265 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 248 266 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 249 267 if (ulCurUnit == (uint32_t)-1) … … 253 271 254 272 case 'T': // --scsitype 255 if ( ulCurVsys == (uint32_t)-1)273 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 256 274 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 257 275 if (ulCurUnit == (uint32_t)-1) … … 261 279 262 280 case 'C': // --controller 263 if ( ulCurVsys == (uint32_t)-1)281 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 264 282 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 265 283 if (ulCurUnit == (uint32_t)-1) … … 269 287 270 288 case 'D': // --disk 271 if ( ulCurVsys == (uint32_t)-1)289 if (actionType == LOCAL && ulCurVsys == (uint32_t)-1) 272 290 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 273 291 if (ulCurUnit == (uint32_t)-1) … … 279 297 if (RT_FAILURE(parseImportOptions(ValueUnion.psz, &options))) 280 298 return errorArgument("Invalid import options '%s'\n", ValueUnion.psz); 299 break; 300 301 /*--cloud and --vsys are orthogonal, only one must be presented*/ 302 case 'j': // --cloud 303 if (fCloud == false && actionType == NOT_SET) 304 { 305 fCloud = true; 306 actionType = CLOUD; 307 } 308 309 if (actionType != CLOUD) 310 return errorSyntax(USAGE_IMPORTAPPLIANCE, 311 "Option \"%s\" can't be used together with \"--vsys\" argument.", 312 GetState.pDef->pszLong); 313 314 ulCurVsys = 0; 315 break; 316 317 /* Cloud export settings */ 318 case 'k': // --cloudprofile 319 if (actionType != CLOUD) 320 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 321 GetState.pDef->pszLong); 322 mapArgsMapsPerVsys[ulCurVsys]["cloudprofile"] = ValueUnion.psz; 323 break; 324 325 case 'l': // --cloudinstanceid 326 if (actionType != CLOUD) 327 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 328 GetState.pDef->pszLong); 329 mapArgsMapsPerVsys[ulCurVsys]["cloudinstanceid"] = ValueUnion.psz; 281 330 break; 282 331 … … 305 354 } 306 355 307 if ( strOvfFilename.isEmpty())356 if (actionType == LOCAL && strOvfFilename.isEmpty()) 308 357 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Not enough arguments for \"import\" command."); 309 358 … … 313 362 CHECK_ERROR_BREAK(arg->virtualBox, CreateAppliance(pAppliance.asOutParam())); 314 363 364 //in the case of Cloud, append the instance id here because later it's harder to do 365 if (actionType == CLOUD && 366 mapArgsMapsPerVsys[ulCurVsys]["cloudprofile"].isNotEmpty() && 367 mapArgsMapsPerVsys[ulCurVsys]["cloudinstanceid"].isNotEmpty()) 368 { 369 strOvfFilename.append(mapArgsMapsPerVsys[ulCurVsys]["cloudprofile"]); 370 strOvfFilename.append("/"); 371 strOvfFilename.append(mapArgsMapsPerVsys[ulCurVsys]["cloudinstanceid"]); 372 } 373 else 374 return errorSyntax(USAGE_IMPORTAPPLIANCE, "Not enough arguments for import from the Cloud."); 375 315 376 char *pszAbsFilePath; 316 377 if (strOvfFilename.startsWith("S3://", RTCString::CaseInsensitive) || 317 378 strOvfFilename.startsWith("SunCloud://", RTCString::CaseInsensitive) || 318 strOvfFilename.startsWith("webdav://", RTCString::CaseInsensitive)) 379 strOvfFilename.startsWith("webdav://", RTCString::CaseInsensitive) || 380 strOvfFilename.startsWith("OCI://", RTCString::CaseInsensitive)) 319 381 pszAbsFilePath = RTStrDup(strOvfFilename.c_str()); 320 382 else 321 383 pszAbsFilePath = RTPathAbsDup(strOvfFilename.c_str()); 384 322 385 ComPtr<IProgress> progressRead; 323 386 CHECK_ERROR_BREAK(pAppliance, Read(Bstr(pszAbsFilePath).raw(), … … 330 393 Bstr path; /* fetch the path, there is stuff like username/password removed if any */ 331 394 CHECK_ERROR_BREAK(pAppliance, COMGETTER(Path)(path.asOutParam())); 332 // call interpret(); this can yield both warnings and errors, so we need333 // to tinker with the error info a bit334 RTStrmPrintf(g_pStdErr, "Interpreting %ls...\n", path.raw());335 rc = pAppliance->Interpret();336 com::ErrorInfo info0(pAppliance, COM_IIDOF(IAppliance));337 338 com::SafeArray<BSTR> aWarnings;339 if (SUCCEEDED(pAppliance->GetWarnings(ComSafeArrayAsOutParam(aWarnings))))340 {341 size_t cWarnings = aWarnings.size();342 for (unsigned i = 0; i < cWarnings; ++i)343 {344 Bstr bstrWarning(aWarnings[i]);345 RTMsgWarning("%ls.", bstrWarning.raw());346 }347 }348 349 if (FAILED(rc)) // during interpret, after printing warnings350 {351 com::GluePrintErrorInfo(info0);352 com::GluePrintErrorContext("Interpret", __FILE__, __LINE__);353 break;354 }355 356 RTStrmPrintf(g_pStdErr, "OK.\n");357 358 // fetch all disks359 com::SafeArray<BSTR> retDisks;360 CHECK_ERROR_BREAK(pAppliance,361 COMGETTER(Disks)(ComSafeArrayAsOutParam(retDisks)));362 if (retDisks.size() > 0)363 {364 RTPrintf("Disks:\n");365 for (unsigned i = 0; i < retDisks.size(); i++)366 RTPrintf(" %ls\n", retDisks[i]);367 RTPrintf("\n");368 }369 395 370 396 // fetch virtual system descriptions … … 375 401 size_t cVirtualSystemDescriptions = aVirtualSystemDescriptions.size(); 376 402 377 // match command line arguments with virtual system descriptions; 378 // this is only to sort out invalid indices at this time 379 ArgsMapsMap::const_iterator it; 380 for (it = mapArgsMapsPerVsys.begin(); 381 it != mapArgsMapsPerVsys.end(); 382 ++it) 403 if (actionType == LOCAL) 383 404 { 384 uint32_t ulVsys = it->first; 385 if (ulVsys >= cVirtualSystemDescriptions) 386 return errorSyntax(USAGE_IMPORTAPPLIANCE, 387 "Invalid index %RI32 with -vsys option; the OVF contains only %zu virtual system(s).", 388 ulVsys, cVirtualSystemDescriptions); 405 // call interpret(); this can yield both warnings and errors, so we need 406 // to tinker with the error info a bit 407 RTStrmPrintf(g_pStdErr, "Interpreting %ls...\n", path.raw()); 408 rc = pAppliance->Interpret(); 409 com::ErrorInfo info0(pAppliance, COM_IIDOF(IAppliance)); 410 411 com::SafeArray<BSTR> aWarnings; 412 if (SUCCEEDED(pAppliance->GetWarnings(ComSafeArrayAsOutParam(aWarnings)))) 413 { 414 size_t cWarnings = aWarnings.size(); 415 for (unsigned i = 0; i < cWarnings; ++i) 416 { 417 Bstr bstrWarning(aWarnings[i]); 418 RTMsgWarning("%ls.", bstrWarning.raw()); 419 } 420 } 421 422 if (FAILED(rc)) // during interpret, after printing warnings 423 { 424 com::GluePrintErrorInfo(info0); 425 com::GluePrintErrorContext("Interpret", __FILE__, __LINE__); 426 break; 427 } 428 429 RTStrmPrintf(g_pStdErr, "OK.\n"); 430 431 // fetch all disks 432 com::SafeArray<BSTR> retDisks; 433 CHECK_ERROR_BREAK(pAppliance, 434 COMGETTER(Disks)(ComSafeArrayAsOutParam(retDisks))); 435 if (retDisks.size() > 0) 436 { 437 RTPrintf("Disks:\n"); 438 for (unsigned i = 0; i < retDisks.size(); i++) 439 RTPrintf(" %ls\n", retDisks[i]); 440 RTPrintf("\n"); 441 } 442 443 // match command line arguments with virtual system descriptions; 444 // this is only to sort out invalid indices at this time 445 ArgsMapsMap::const_iterator it; 446 for (it = mapArgsMapsPerVsys.begin(); 447 it != mapArgsMapsPerVsys.end(); 448 ++it) 449 { 450 uint32_t ulVsys = it->first; 451 if (ulVsys >= cVirtualSystemDescriptions) 452 return errorSyntax(USAGE_IMPORTAPPLIANCE, 453 "Invalid index %RI32 with -vsys option; the OVF contains only %zu virtual system(s).", 454 ulVsys, cVirtualSystemDescriptions); 455 } 389 456 } 390 457 … … 920 987 case VirtualSystemDescriptionType_CloudKeepObject: 921 988 case VirtualSystemDescriptionType_CloudLaunchInstance: 989 case VirtualSystemDescriptionType_CloudInstanceId: 990 case VirtualSystemDescriptionType_CloudImageId: 922 991 case VirtualSystemDescriptionType_Miscellaneous: 923 992 /** @todo VirtualSystemDescriptionType_Miscellaneous? */ … … 1041 1110 }; 1042 1111 1043 enum1044 {1045 NOT_SET, LOCAL, CLOUD1046 } exportType;1047 1048 1112 RTEXITCODE handleExportAppliance(HandlerArg *a) 1049 1113 { … … 1054 1118 bool fManifest = false; // the default 1055 1119 bool fCloud = false; // the default 1056 exportType = NOT_SET;1120 actionType = NOT_SET; 1057 1121 bool fExportISOImages = false; // the default 1058 1122 com::SafeArray<ExportOptions_T> options; … … 1109 1173 1110 1174 case 's': // --vsys 1111 if (fCloud == false && exportType == NOT_SET)1112 exportType = LOCAL;1113 1114 if ( exportType != LOCAL)1175 if (fCloud == false && actionType == NOT_SET) 1176 actionType = LOCAL; 1177 1178 if (actionType != LOCAL) 1115 1179 return errorSyntax(USAGE_EXPORTAPPLIANCE, 1116 1180 "Option \"%s\" can't be used together with \"--cloud\" argument.", … … 1121 1185 1122 1186 case 'V': // --vmname 1123 if ( exportType == NOT_SET || ulCurVsys == (uint32_t)-1)1187 if (actionType == NOT_SET || ulCurVsys == (uint32_t)-1) 1124 1188 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys or --cloud argument.", 1125 1189 GetState.pDef->pszLong); … … 1128 1192 1129 1193 case 'p': // --product 1130 if ( exportType != LOCAL)1194 if (actionType != LOCAL) 1131 1195 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1132 1196 mapArgsMapsPerVsys[ulCurVsys]["product"] = ValueUnion.psz; … … 1134 1198 1135 1199 case 'P': // --producturl 1136 if ( exportType != LOCAL)1200 if (actionType != LOCAL) 1137 1201 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1138 1202 mapArgsMapsPerVsys[ulCurVsys]["producturl"] = ValueUnion.psz; … … 1140 1204 1141 1205 case 'n': // --vendor 1142 if ( exportType != LOCAL)1206 if (actionType != LOCAL) 1143 1207 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1144 1208 mapArgsMapsPerVsys[ulCurVsys]["vendor"] = ValueUnion.psz; … … 1146 1210 1147 1211 case 'N': // --vendorurl 1148 if ( exportType != LOCAL)1212 if (actionType != LOCAL) 1149 1213 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1150 1214 mapArgsMapsPerVsys[ulCurVsys]["vendorurl"] = ValueUnion.psz; … … 1152 1216 1153 1217 case 'v': // --version 1154 if ( exportType != LOCAL)1218 if (actionType != LOCAL) 1155 1219 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1156 1220 mapArgsMapsPerVsys[ulCurVsys]["version"] = ValueUnion.psz; … … 1158 1222 1159 1223 case 'd': // --description 1160 if ( exportType != LOCAL)1224 if (actionType != LOCAL) 1161 1225 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1162 1226 mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz; … … 1164 1228 1165 1229 case 'e': // --eula 1166 if ( exportType != LOCAL)1230 if (actionType != LOCAL) 1167 1231 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1168 1232 mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz; … … 1170 1234 1171 1235 case 'E': // --eulafile 1172 if ( exportType != LOCAL)1236 if (actionType != LOCAL) 1173 1237 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong); 1174 1238 mapArgsMapsPerVsys[ulCurVsys]["eulafile"] = ValueUnion.psz; … … 1182 1246 /*--cloud and --vsys are orthogonal, only one must be presented*/ 1183 1247 case 'C': // --cloud 1184 if (fCloud == false && exportType == NOT_SET)1248 if (fCloud == false && actionType == NOT_SET) 1185 1249 { 1186 1250 fCloud = true; 1187 exportType = CLOUD;1251 actionType = CLOUD; 1188 1252 } 1189 1253 1190 if ( exportType != CLOUD)1254 if (actionType != CLOUD) 1191 1255 return errorSyntax(USAGE_EXPORTAPPLIANCE, 1192 1256 "Option \"%s\" can't be used together with \"--vsys\" argument.", … … 1198 1262 /* Cloud export settings */ 1199 1263 case 'S': // --cloudshape 1200 if ( exportType != CLOUD)1264 if (actionType != CLOUD) 1201 1265 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1202 1266 GetState.pDef->pszLong); … … 1205 1269 1206 1270 case 'D': // --clouddomain 1207 if ( exportType != CLOUD)1271 if (actionType != CLOUD) 1208 1272 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1209 1273 GetState.pDef->pszLong); … … 1212 1276 1213 1277 case 'R': // --clouddisksize 1214 if ( exportType != CLOUD)1278 if (actionType != CLOUD) 1215 1279 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1216 1280 GetState.pDef->pszLong); … … 1219 1283 1220 1284 case 'B': // --cloudbucket 1221 if ( exportType != CLOUD)1285 if (actionType != CLOUD) 1222 1286 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1223 1287 GetState.pDef->pszLong); … … 1226 1290 1227 1291 case 'Q': // --cloudocivcn 1228 if ( exportType != CLOUD)1292 if (actionType != CLOUD) 1229 1293 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1230 1294 GetState.pDef->pszLong); … … 1233 1297 1234 1298 case 'A': // --cloudpublicip 1235 if ( exportType != CLOUD)1299 if (actionType != CLOUD) 1236 1300 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1237 1301 GetState.pDef->pszLong); … … 1240 1304 1241 1305 case 'F': // --cloudprofile 1242 if ( exportType != CLOUD)1306 if (actionType != CLOUD) 1243 1307 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1244 1308 GetState.pDef->pszLong); … … 1247 1311 1248 1312 case 'T': // --cloudocisubnet 1249 if ( exportType != CLOUD)1313 if (actionType != CLOUD) 1250 1314 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1251 1315 GetState.pDef->pszLong); … … 1254 1318 1255 1319 case 'K': // --cloudkeepobject 1256 if ( exportType != CLOUD)1320 if (actionType != CLOUD) 1257 1321 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1258 1322 GetState.pDef->pszLong); … … 1261 1325 1262 1326 case 'L': // --cloudlaunchinstance 1263 if ( exportType != CLOUD)1327 if (actionType != CLOUD) 1264 1328 return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.", 1265 1329 GetState.pDef->pszLong); -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r78351 r78428 3627 3627 <enum 3628 3628 name="VirtualSystemDescriptionType" 3629 uuid="4 25d0e49-eb9c-43e8-bb0d-be7f78fd3b47"3629 uuid="48875667-19f6-4329-a208-735adf9a47ee" 3630 3630 > 3631 3631 <desc>Used with <link to="IVirtualSystemDescription" /> to describe the type of … … 3682 3682 <const name="CloudKeepObject" value="35" /> 3683 3683 <const name="CloudLaunchInstance" value="36" /> 3684 <const name="CloudInstanceId" value="37" /> 3685 <const name="CloudImageId" value="38" /> 3684 3686 </enum> 3685 3687 … … 25740 25742 name="ICloudClient" extends="$unknown" 25741 25743 uuid="7acc426a-5f8f-11e9-9032-1b0da54759a8" 25742 wsmap="managed" reservedMethods="1 3" reservedAttributes="8"25744 wsmap="managed" reservedMethods="11" reservedAttributes="8" 25743 25745 > 25744 25746 … … 25819 25821 Progress object to track the operation completion. 25820 25822 </desc> 25823 </param> 25824 </method> 25825 25826 <method name="getInstanceInfo" const="yes"> 25827 <desc> 25828 Returns the information about an instance in the Cloud. 25829 </desc> 25830 <param name="instanceId" type="wstring" dir="in"> 25831 <desc>What to search for. This is the instance ID.</desc> 25832 </param> 25833 <param name="description" type="IVirtualSystemDescription" dir="in"> 25834 <desc>VirtualSystemDescription object which is describing a machine</desc> 25835 </param> 25836 </method> 25837 25838 <method name="importInstance"> 25839 <desc> 25840 Import an existing instance with passed id to the local host. 25841 </desc> 25842 <param name="description" type="IVirtualSystemDescription" dir="in"> 25843 <desc>VirtualSystemDescription object which is describing a machine and all required parameters.</desc> 25844 </param> 25845 <param name="uid" type="wstring" dir="in"> 25846 <desc>the UUID of instance imported from the Cloud.</desc> 25847 </param> 25848 <param name="virtualBox" type="IVirtualBox" dir="in"> 25849 <desc>Reference to the server-side API root object.</desc> 25850 </param> 25851 <param name="progress" type="IProgress" dir="in"> 25852 <desc>Progress object to track the operation completion.</desc> 25821 25853 </param> 25822 25854 </method> -
trunk/src/VBox/Main/include/ApplianceImpl.h
r78255 r78428 102 102 HRESULT createVFSExplorer(const com::Utf8Str &aURI, 103 103 ComPtr<IVFSExplorer> &aExplorer); 104 HRESULT createVirtualSystemDescriptions(ULONG aRequested, ULONG *aCreated);105 104 HRESULT write(const com::Utf8Str &aFormat, 106 105 const std::vector<ExportOptions_T> &aOptions, … … 112 111 HRESULT addPasswords(const std::vector<com::Utf8Str> &aIdentifiers, 113 112 const std::vector<com::Utf8Str> &aPasswords); 114 113 HRESULT createVirtualSystemDescriptions(ULONG aRequested, ULONG *aCreated); 115 114 /** weak VirtualBox parent */ 116 115 VirtualBox* const mVirtualBox; … … 124 123 Data *m; 125 124 126 enum SetUpProgressMode { ImportFile, ImportS3, WriteFile, WriteS3, ExportCloud };125 enum SetUpProgressMode { ImportFile, ImportS3, WriteFile, WriteS3, ExportCloud, ImportCloud }; 127 126 128 127 /** @name General stuff … … 143 142 static void i_importOrExportThreadTask(TaskOVF *pTask); 144 143 static void i_exportOPCThreadTask(TaskOPC *pTask); 145 static void i_ exportCloudThreadTask(TaskCloud *pTask);144 static void i_importOrExportCloudThreadTask(TaskCloud *pTask); 146 145 147 146 HRESULT i_initBackendNames(); … … 171 170 HRESULT i_readSignatureFile(TaskOVF *pTask, RTVFSIOSTREAM hIosCert, const char *pszSubFileNm); 172 171 HRESULT i_readTailProcessing(TaskOVF *pTask); 172 HRESULT i_gettingCloudData(TaskCloud *pTask); 173 173 174 /** @} */ 174 175 … … 215 216 void i_importDecompressFile(ImportStack &stack, Utf8Str const &rstrSrcPath, Utf8Str const &rstrDstPath, 216 217 const char *pszManifestEntry); 218 HRESULT i_importCloudImpl(TaskCloud *pTask); 217 219 /** @} */ 218 220 … … 228 230 HRESULT i_writeFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock); 229 231 HRESULT i_writeFSOPC(TaskOPC *pTask); 230 HRESULT i_ writeFSCloud(TaskCloud *pTask);232 HRESULT i_exportCloudImpl(TaskCloud *pTask); 231 233 HRESULT i_writeFSImpl(TaskOVF *pTask, AutoWriteLockBase &writeLock, RTVFSFSSTREAM hVfsFssDst); 232 234 HRESULT i_writeBufferToFile(RTVFSFSSTREAM hVfsFssDst, const char *pszFilename, const void *pvContent, size_t cbContent); -
trunk/src/VBox/Main/include/ApplianceImplPrivate.h
r76562 r78428 339 339 enum TaskType 340 340 { 341 Export 341 Export, 342 Import, 343 ReadData 342 344 }; 343 345 … … 353 355 rc(S_OK) 354 356 { 355 m_strTaskName = "CloudExpt"; 357 switch (taskType) 358 { 359 case TaskCloud::Export: m_strTaskName = "CloudExpt"; break; 360 case TaskCloud::Import: m_strTaskName = "CloudImpt"; break; 361 case TaskCloud::ReadData: m_strTaskName = "CloudRead"; break; 362 default: m_strTaskName = "CloudTask"; break; 363 } 356 364 } 357 365 … … 371 379 void handler() 372 380 { 373 Appliance::i_ exportCloudThreadTask(this);381 Appliance::i_importOrExportCloudThreadTask(this); 374 382 } 375 383 }; -
trunk/src/VBox/Main/src-server/ApplianceImpl.cpp
r78256 r78428 1104 1104 } 1105 1105 case ExportCloud: 1106 cOperations = 1 + 9;//7 1107 ulTotalOperationsWeight = 100*cOperations; 1108 m->ulWeightForXmlOperation = 100; 1106 case ImportCloud: 1109 1107 break; 1110 1108 } … … 1340 1338 */ 1341 1339 /* static */ 1342 void Appliance::i_ exportCloudThreadTask(TaskCloud *pTask)1340 void Appliance::i_importOrExportCloudThreadTask(TaskCloud *pTask) 1343 1341 { 1344 1342 LogFlowFuncEnter(); … … 1351 1349 { 1352 1350 case TaskCloud::Export: 1353 pTask->rc = pAppliance->i_ writeFSCloud(pTask);1351 pTask->rc = pAppliance->i_exportCloudImpl(pTask); 1354 1352 break; 1355 1353 case TaskCloud::Import: 1354 pTask->rc = pAppliance->i_importCloudImpl(pTask); 1355 break; 1356 case TaskCloud::ReadData: 1357 pTask->rc = pAppliance->i_gettingCloudData(pTask); 1358 break; 1356 1359 default: 1357 1360 AssertFailed(); … … 1411 1414 1412 1415 /* Not necessary on a file based URI */ 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1416 // if (locInfo.storageType != VFSType_File) 1417 // { 1418 // size_t uppos = strUri.find("@"); /* username:password combo */ 1419 // if (uppos != Utf8Str::npos) 1420 // { 1421 // locInfo.strUsername = strUri.substr(0, uppos); 1422 // strUri = strUri.substr(uppos + 1); 1423 // size_t upos = locInfo.strUsername.find(":"); 1424 // if (upos != Utf8Str::npos) 1425 // { 1426 // locInfo.strPassword = locInfo.strUsername.substr(upos + 1); 1427 // locInfo.strUsername = locInfo.strUsername.substr(0, upos); 1428 // } 1429 // } 1430 // size_t hpos = strUri.find("/"); /* hostname part */ 1431 // if (hpos != Utf8Str::npos) 1432 // { 1433 // locInfo.strHostname = strUri.substr(0, hpos); 1434 // strUri = strUri.substr(hpos); 1435 // } 1436 // } 1434 1437 1435 1438 locInfo.strPath = strUri; -
trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp
r76592 r78428 653 653 i_parseURI(aPath, m->locInfo); 654 654 655 if (m->locInfo.storageType == VFSType_Cloud) //(isCloudDestination(aPath))655 if (m->locInfo.storageType == VFSType_Cloud) 656 656 { 657 657 rc = S_OK; … … 2242 2242 * instance with this image in the OCI Compute service. 2243 2243 */ 2244 HRESULT Appliance::i_ writeFSCloud(TaskCloud *pTask)2244 HRESULT Appliance::i_exportCloudImpl(TaskCloud *pTask) 2245 2245 { 2246 2246 LogFlowFuncEnter(); … … 2250 2250 hrc = mVirtualBox->COMGETTER(CloudProviderManager)(cpm.asOutParam()); 2251 2251 if (FAILED(hrc)) 2252 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr(" Cloud: Cloud provider manager object wasn't found"));2252 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%: Cloud provider manager object wasn't found", __FUNCTION__)); 2253 2253 2254 2254 Utf8Str strProviderName = pTask->locInfo.strProvider; … … 2258 2258 2259 2259 if (FAILED(hrc)) 2260 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr(" Cloud: Cloud provider object wasn't found"));2260 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud provider object wasn't found", __FUNCTION__)); 2261 2261 2262 2262 ComPtr<IVirtualSystemDescription> vsd = m->virtualSystemDescriptions.front(); … … 2279 2279 Utf8Str profileName(aVBoxValues[0]); 2280 2280 if (profileName.isEmpty()) 2281 return setErrorVrc(VBOX_E_OBJECT_NOT_FOUND, tr(" Cloud: Cloud user profile name wasn't found"));2281 return setErrorVrc(VBOX_E_OBJECT_NOT_FOUND, tr("%s: Cloud user profile name wasn't found", __FUNCTION__)); 2282 2282 2283 2283 hrc = cloudProvider->GetProfileByName(aVBoxValues[0], cloudProfile.asOutParam()); 2284 2284 if (FAILED(hrc)) 2285 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr(" Cloud: Cloud profile object wasn't found"));2285 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud profile object wasn't found", __FUNCTION__)); 2286 2286 2287 2287 ComObjPtr<ICloudClient> cloudClient; 2288 2288 hrc = cloudProfile->CreateCloudClient(cloudClient.asOutParam()); 2289 2289 if (FAILED(hrc)) 2290 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("Cloud: Cloud client object wasn't found")); 2291 2292 LogRel(("Appliance::i_writeFSCloud(): calling CloudClient::ExportLaunchVM\n")); 2290 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud client object wasn't found", __FUNCTION__)); 2293 2291 2294 2292 if (m->virtualSystemDescriptions.size() == 1) -
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r78104 r78428 88 88 } 89 89 90 // see if we can handle this file; for now we insist it has an ovf/ova extension91 if ( !aFile.endsWith(".ovf", Utf8Str::CaseInsensitive)92 && !aFile.endsWith(".ova", Utf8Str::CaseInsensitive))93 return setError(VBOX_E_FILE_ERROR, tr("Appliance file must have .ovf or .ova extension"));94 95 90 ComObjPtr<Progress> progress; 96 91 try … … 98 93 /* Parse all necessary info out of the URI */ 99 94 i_parseURI(aFile, m->locInfo); 95 96 // see if we can handle this file; for now we insist it has an ovf/ova extension 97 if ( m->locInfo.storageType == VFSType_File 98 && !aFile.endsWith(".ovf", Utf8Str::CaseInsensitive) 99 && !aFile.endsWith(".ova", Utf8Str::CaseInsensitive)) 100 return setError(VBOX_E_FILE_ERROR, tr("Appliance file must have .ovf or .ova extension")); 101 100 102 i_readImpl(m->locInfo, progress); 101 103 } … … 790 792 return E_ACCESSDENIED; 791 793 792 if (!m->pReader) 794 //check for the local import only. For import from the Cloud m->pReader is always NULL. 795 if (m->locInfo.storageType == VFSType_File && !m->pReader) 793 796 return setError(E_FAIL, 794 797 tr("Cannot import machines without reading it first (call read() before i_importMachines())")); … … 1121 1124 bstrDesc.raw(), 1122 1125 TRUE /* aCancelable */); 1126 1127 else if (aLocInfo.storageType == VFSType_Cloud) 1128 /* 1 operation only for now */ 1129 rc = aProgress->init(mVirtualBox, static_cast<IAppliance*>(this), 1130 "Getting cloud instance information...", 1131 TRUE /* aCancelable */); 1123 1132 else 1124 1133 /* 4/5 is downloading, 1/5 is reading */ … … 1134 1143 1135 1144 /* Initialize our worker task */ 1136 TaskOVF *task = NULL; 1145 TaskOVF *ovfTask = NULL; 1146 TaskCloud *cloudTask = NULL; 1137 1147 try 1138 1148 { 1139 task = new TaskOVF(this, TaskOVF::Read, aLocInfo, aProgress); 1140 } 1149 if (aLocInfo.storageType == VFSType_File) 1150 { 1151 ovfTask = new TaskOVF(this, TaskOVF::Read, aLocInfo, aProgress); 1152 rc = ovfTask->createThread(); 1153 if (FAILED(rc)) throw rc; 1154 } 1155 else if (aLocInfo.storageType == VFSType_Cloud) 1156 { 1157 cloudTask = new TaskCloud(this, TaskCloud::ReadData, aLocInfo, aProgress); 1158 rc = cloudTask->createThread(); 1159 if (FAILED(rc)) throw rc; 1160 } 1161 } 1162 catch (HRESULT aRc) 1163 { 1164 rc = aRc; 1165 } 1141 1166 catch (...) 1142 1167 { 1143 throw setError(VBOX_E_OBJECT_NOT_FOUND, 1144 tr("Could not create TaskOVF object for reading the OVF from disk")); 1145 } 1146 1147 rc = task->createThread(); 1148 if (FAILED(rc)) throw rc; 1168 rc = setError(VBOX_E_OBJECT_NOT_FOUND, 1169 tr("Could not create a task object for reading the Appliance data")); 1170 } 1171 1172 if (FAILED(rc)) 1173 { 1174 if (ovfTask) 1175 delete ovfTask; 1176 if (cloudTask) 1177 delete cloudTask; 1178 throw rc; 1179 } 1180 } 1181 1182 HRESULT Appliance::i_gettingCloudData(TaskCloud *pTask) 1183 { 1184 LogFlowFuncEnter(); 1185 LogFlowFunc(("Appliance %p\n", this)); 1186 1187 AutoCaller autoCaller(this); 1188 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1189 1190 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS); 1191 1192 HRESULT hrc = S_OK; 1193 1194 try 1195 { 1196 Utf8Str strBasename(pTask->locInfo.strPath); 1197 RTCList<RTCString, RTCString *> parts = strBasename.split("/"); 1198 if (parts.size() != 2)//profile + instance id 1199 { 1200 return setErrorVrc(VERR_MISMATCH, tr("%s: The profile name or instance id are absent or" 1201 "contain unsupported characters.", __FUNCTION__)); 1202 } 1203 1204 //Get information about the passed cloud instance 1205 ComPtr<ICloudProviderManager> cpm; 1206 hrc = mVirtualBox->COMGETTER(CloudProviderManager)(cpm.asOutParam()); 1207 if (FAILED(hrc)) 1208 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud provider manager object wasn't found", __FUNCTION__)); 1209 1210 Utf8Str strProviderName = pTask->locInfo.strProvider; 1211 ComPtr<ICloudProvider> cloudProvider; 1212 ComPtr<ICloudProfile> cloudProfile; 1213 hrc = cpm->GetProviderByShortName(Bstr(strProviderName.c_str()).raw(), cloudProvider.asOutParam()); 1214 1215 if (FAILED(hrc)) 1216 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud provider object wasn't found", __FUNCTION__)); 1217 1218 Utf8Str profileName(parts.at(0));//profile 1219 if (profileName.isEmpty()) 1220 return setErrorVrc(VBOX_E_OBJECT_NOT_FOUND, tr("%s: Cloud user profile name wasn't found", __FUNCTION__)); 1221 1222 hrc = cloudProvider->GetProfileByName(Bstr(parts.at(0)).raw(), cloudProfile.asOutParam()); 1223 if (FAILED(hrc)) 1224 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud profile object wasn't found", __FUNCTION__)); 1225 1226 ComObjPtr<ICloudClient> cloudClient; 1227 hrc = cloudProfile->CreateCloudClient(cloudClient.asOutParam()); 1228 if (FAILED(hrc)) 1229 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud client object wasn't found", __FUNCTION__)); 1230 1231 m->virtualSystemDescriptions.clear();//clear all for assurance before creating new 1232 std::vector<ComPtr<IVirtualSystemDescription> > vsdArray; 1233 uint32_t requestedVSDnums = 1; 1234 uint32_t newVSDnums = 0; 1235 hrc = createVirtualSystemDescriptions(requestedVSDnums, &newVSDnums); 1236 if (FAILED(hrc)) throw hrc; 1237 if (requestedVSDnums != newVSDnums) 1238 throw setErrorVrc(VERR_MISMATCH, tr("%s: Requested and created numbers of VSD are differ.", __FUNCTION__)); 1239 1240 hrc = getVirtualSystemDescriptions(vsdArray); 1241 if (FAILED(hrc)) throw hrc; 1242 ComPtr<IVirtualSystemDescription> instanceDescription = vsdArray[0]; 1243 1244 LogRel(("%s: calling CloudClient::GetInstanceInfo()\n", __FUNCTION__)); 1245 hrc = cloudClient->GetInstanceInfo(Bstr(parts.at(1)).raw(), instanceDescription);//instance id 1246 if (FAILED(hrc)) throw hrc; 1247 1248 // set cloud profile 1249 instanceDescription->AddDescription(VirtualSystemDescriptionType_CloudProfileName, 1250 Bstr(profileName).raw(), 1251 Bstr(profileName).raw()); 1252 // set name 1253 Utf8Str strSetting = "cloud VM ("; 1254 strSetting.append(parts.at(1)).append(")"); 1255 // set description 1256 strSetting = "VM with id "; 1257 strSetting.append(parts.at(1)).append(" imported from the cloud provider ").append(strProviderName); 1258 1259 // description 1260 instanceDescription->AddDescription(VirtualSystemDescriptionType_Description, 1261 Bstr(strSetting).raw(), 1262 Bstr(strSetting).raw()); 1263 } 1264 catch (HRESULT arc) 1265 { 1266 LogFlowFunc(("arc=%Rhrc\n", arc)); 1267 hrc = arc; 1268 } 1269 1270 LogFlowFunc(("rc=%Rhrc\n", hrc)); 1271 LogFlowFuncLeave(); 1272 1273 return hrc; 1274 } 1275 1276 /** 1277 * Actual worker code for import from the Cloud 1278 * 1279 * @param pTask 1280 * @return 1281 */ 1282 HRESULT Appliance::i_importCloudImpl(TaskCloud *pTask) 1283 { 1284 LogFlowFuncEnter(); 1285 LogFlowFunc(("Appliance %p\n", this)); 1286 1287 /* Change the appliance state so we can safely leave the lock while doing 1288 * time-consuming operations; also the below method calls do all kinds of 1289 * locking which conflicts with the appliance object lock. */ 1290 AutoWriteLock writeLock(this COMMA_LOCKVAL_SRC_POS); 1291 /* Check if the appliance is currently busy. */ 1292 if (!i_isApplianceIdle()) 1293 return E_ACCESSDENIED; 1294 /* Set the internal state to importing. */ 1295 m->state = Data::ApplianceImporting; 1296 1297 HRESULT hrc = S_OK; 1298 1299 /* Clear the list of imported machines, if any */ 1300 m->llGuidsMachinesCreated.clear(); 1301 1302 /* 1303 * Actual code for the cloud import 1304 * 1305 */ 1306 1307 ComPtr<ICloudProviderManager> cpm; 1308 hrc = mVirtualBox->COMGETTER(CloudProviderManager)(cpm.asOutParam()); 1309 if (FAILED(hrc)) 1310 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud provider manager object wasn't found", __FUNCTION__)); 1311 1312 Utf8Str strProviderName = pTask->locInfo.strProvider; 1313 ComPtr<ICloudProvider> cloudProvider; 1314 ComPtr<ICloudProfile> cloudProfile; 1315 hrc = cpm->GetProviderByShortName(Bstr(strProviderName.c_str()).raw(), cloudProvider.asOutParam()); 1316 1317 if (FAILED(hrc)) 1318 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud provider object wasn't found", __FUNCTION__)); 1319 1320 ComPtr<IVirtualSystemDescription> vsd = m->virtualSystemDescriptions.front(); 1321 1322 com::SafeArray<VirtualSystemDescriptionType_T> retTypes; 1323 com::SafeArray<BSTR> aRefs; 1324 com::SafeArray<BSTR> aOvfValues; 1325 com::SafeArray<BSTR> aVBoxValues; 1326 com::SafeArray<BSTR> aExtraConfigValues; 1327 1328 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_CloudProfileName, 1329 ComSafeArrayAsOutParam(retTypes), 1330 ComSafeArrayAsOutParam(aRefs), 1331 ComSafeArrayAsOutParam(aOvfValues), 1332 ComSafeArrayAsOutParam(aVBoxValues), 1333 ComSafeArrayAsOutParam(aExtraConfigValues)); 1334 if (FAILED(hrc)) 1335 return hrc; 1336 1337 Utf8Str profileName(aVBoxValues[0]); 1338 if (profileName.isEmpty()) 1339 return setErrorVrc(VBOX_E_OBJECT_NOT_FOUND, tr("%s: Cloud user profile name wasn't found", __FUNCTION__)); 1340 1341 hrc = cloudProvider->GetProfileByName(aVBoxValues[0], cloudProfile.asOutParam()); 1342 if (FAILED(hrc)) 1343 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud profile object wasn't found", __FUNCTION__)); 1344 1345 ComObjPtr<ICloudClient> cloudClient; 1346 hrc = cloudProfile->CreateCloudClient(cloudClient.asOutParam()); 1347 if (FAILED(hrc)) 1348 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud client object wasn't found", __FUNCTION__)); 1349 1350 if (m->virtualSystemDescriptions.size() == 1) 1351 { 1352 do 1353 { 1354 ComPtr<IVirtualBox> VBox(mVirtualBox); 1355 retTypes.setNull(); 1356 aRefs.setNull(); 1357 aOvfValues.setNull(); 1358 aVBoxValues.setNull(); 1359 aExtraConfigValues.setNull(); 1360 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_CloudInstanceId, 1361 ComSafeArrayAsOutParam(retTypes), 1362 ComSafeArrayAsOutParam(aRefs), 1363 ComSafeArrayAsOutParam(aOvfValues), 1364 ComSafeArrayAsOutParam(aVBoxValues), 1365 ComSafeArrayAsOutParam(aExtraConfigValues)); 1366 if (FAILED(hrc)) 1367 break; 1368 1369 ComPtr<IProgress> pProgress; 1370 pTask->pProgress.queryInterfaceTo(pProgress.asOutParam()); 1371 1372 LogRel(("%s: calling CloudClient::ImportInstance\n", __FUNCTION__)); 1373 hrc = cloudClient->ImportInstance(m->virtualSystemDescriptions.front(), 1374 aVBoxValues[0], 1375 VBox, 1376 pProgress); 1377 Bstr instId(aVBoxValues[0]); 1378 Utf8Str strInsId(instId); 1379 if (FAILED(hrc)) 1380 { 1381 hrc = setError(hrc, "%s: Import cloud instance \'%s\' failed\n", __FUNCTION__, strInsId.c_str()); 1382 break; 1383 } 1384 1385 Utf8Str vsdData; 1386 1387 retTypes.setNull(); 1388 aRefs.setNull(); 1389 aOvfValues.setNull(); 1390 aVBoxValues.setNull(); 1391 aExtraConfigValues.setNull(); 1392 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_CPU, 1393 ComSafeArrayAsOutParam(retTypes), 1394 ComSafeArrayAsOutParam(aRefs), 1395 ComSafeArrayAsOutParam(aOvfValues), 1396 ComSafeArrayAsOutParam(aVBoxValues), 1397 ComSafeArrayAsOutParam(aExtraConfigValues)); 1398 if (FAILED(hrc)) 1399 break; 1400 vsdData = aVBoxValues[0]; 1401 if (vsdData.isEmpty()) 1402 LogRel(("%s: Number of CPUs wasn't found\n", __FUNCTION__)); 1403 else 1404 LogRel(("%s: Number of CPUs is %s\n", __FUNCTION__, vsdData.c_str())); 1405 1406 retTypes.setNull(); 1407 aRefs.setNull(); 1408 aOvfValues.setNull(); 1409 aVBoxValues.setNull(); 1410 aExtraConfigValues.setNull(); 1411 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_Memory, 1412 ComSafeArrayAsOutParam(retTypes), 1413 ComSafeArrayAsOutParam(aRefs), 1414 ComSafeArrayAsOutParam(aOvfValues), 1415 ComSafeArrayAsOutParam(aVBoxValues), 1416 ComSafeArrayAsOutParam(aExtraConfigValues)); 1417 if (FAILED(hrc)) 1418 break; 1419 vsdData = aVBoxValues[0]; 1420 if (vsdData.isEmpty()) 1421 LogRel(("%s: Size of RAM wasn't found\n", __FUNCTION__)); 1422 else 1423 LogRel(("%s: Size of RAM is %sMB\n", __FUNCTION__, vsdData.c_str())); 1424 1425 retTypes.setNull(); 1426 aRefs.setNull(); 1427 aOvfValues.setNull(); 1428 aVBoxValues.setNull(); 1429 aExtraConfigValues.setNull(); 1430 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_OS, 1431 ComSafeArrayAsOutParam(retTypes), 1432 ComSafeArrayAsOutParam(aRefs), 1433 ComSafeArrayAsOutParam(aOvfValues), 1434 ComSafeArrayAsOutParam(aVBoxValues), 1435 ComSafeArrayAsOutParam(aExtraConfigValues)); 1436 if (FAILED(hrc)) 1437 break; 1438 vsdData = aVBoxValues[0]; 1439 if (vsdData.isEmpty()) 1440 LogRel(("%s: OS type wasn't found", __FUNCTION__)); 1441 else 1442 LogRel(("%s: OS type is %s\n", __FUNCTION__, vsdData.c_str())); 1443 1444 retTypes.setNull(); 1445 aRefs.setNull(); 1446 aOvfValues.setNull(); 1447 aVBoxValues.setNull(); 1448 aExtraConfigValues.setNull(); 1449 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_Name, 1450 ComSafeArrayAsOutParam(retTypes), 1451 ComSafeArrayAsOutParam(aRefs), 1452 ComSafeArrayAsOutParam(aOvfValues), 1453 ComSafeArrayAsOutParam(aVBoxValues), 1454 ComSafeArrayAsOutParam(aExtraConfigValues)); 1455 if (FAILED(hrc)) 1456 break; 1457 vsdData = aVBoxValues[0]; 1458 if (vsdData.isEmpty()) 1459 LogRel(("%s: VM name wasn't found", __FUNCTION__)); 1460 else 1461 LogRel(("%s: VM name is %s\n", __FUNCTION__, vsdData.c_str())); 1462 } while (0); 1463 } 1464 else 1465 hrc = setErrorVrc(VERR_MISMATCH, tr("Import from Cloud isn't supported for more than one VM instance.")); 1466 1467 if (FAILED(hrc)) 1468 { 1469 //some roll-back actions 1470 } 1471 else 1472 { 1473 //continue and create new VM using data from VSD and downloaded image as base image 1474 //The downloaded image should be converted to VDI/VMDK if it has another format 1475 } 1476 1477 /* Reset the state so others can call methods again */ 1478 m->state = Data::ApplianceIdle; 1479 1480 LogFlowFunc(("rc=%Rhrc\n", hrc)); 1481 LogFlowFuncLeave(); 1482 return hrc; 1149 1483 } 1150 1484 … … 1981 2315 if (locInfo.storageType == VFSType_File) 1982 2316 mode = ImportFile; 2317 else if (locInfo.storageType == VFSType_Cloud) 2318 mode = ImportCloud; 1983 2319 else 1984 2320 mode = ImportS3; 1985 2321 1986 rc = i_setUpProgress(progress,1987 BstrFmt(tr("Importing appliance '%s'"), locInfo.strPath.c_str()),1988 mode);1989 if (FAILED(rc)) throw rc;1990 1991 2322 /* Initialize our worker task */ 1992 TaskOVF* task = NULL; 2323 TaskOVF* ovfTask = NULL; 2324 TaskCloud* cloudTask = NULL; 1993 2325 try 1994 2326 { 1995 task = new TaskOVF(this, TaskOVF::Import, locInfo, progress); 1996 } 1997 catch(...) 1998 { 1999 delete task; 2000 throw rc = setError(VBOX_E_OBJECT_NOT_FOUND, 2001 tr("Could not create TaskOVF object for importing OVF data into VirtualBox")); 2002 } 2003 2004 rc = task->createThread(); 2005 if (FAILED(rc)) throw rc; 2327 if (mode == ImportFile) 2328 { 2329 rc = i_setUpProgress(progress, 2330 BstrFmt(tr("Importing appliance '%s'"), locInfo.strPath.c_str()), 2331 mode); 2332 if (FAILED(rc)) throw rc; 2333 2334 ovfTask = new TaskOVF(this, TaskOVF::Import, locInfo, progress); 2335 rc = ovfTask->createThread(); 2336 } 2337 else if (mode == ImportCloud) 2338 { 2339 /* 2340 1. Create a custom imaghe from the instance 2341 2. Import the custom image into the Object Storage (OCI format - TAR file with QCOW2 image and JSON file) 2342 3. Download the object from the Object Storage 2343 4. Open the object, extract QCOW2 image and convert one QCOW2->VDI 2344 5. Create VM with user settings and attach the converted image to VM 2345 6. Lauch VM. 2346 */ 2347 progress.createObject(); 2348 if (locInfo.strProvider.equals("OCI")) 2349 { 2350 progress->init(mVirtualBox, static_cast<IAppliance*>(this), 2351 Bstr("Importing VM from Cloud...").raw(), 2352 TRUE /* aCancelable */, 2353 6, // ULONG cOperations, 2354 750, // ULONG ulTotalOperationsWeight, 2355 Bstr("Importing VM from Cloud...").raw(), // aFirstOperationDescription 2356 10); // ULONG ulFirstOperationWeight 2357 } 2358 else 2359 return setErrorVrc(VBOX_E_NOT_SUPPORTED, 2360 tr("Only \"OCI\" cloud provider is supported for now. \"%s\" isn't supported."), 2361 locInfo.strProvider.c_str()); 2362 2363 cloudTask = new TaskCloud(this, TaskCloud::Import, locInfo, progress); 2364 rc = cloudTask->createThread(); 2365 if (FAILED(rc)) throw rc; 2366 } 2367 } 2368 catch (HRESULT aRc) 2369 { 2370 rc = aRc; 2371 } 2372 catch (...) 2373 { 2374 rc = setError(VBOX_E_OBJECT_NOT_FOUND, 2375 tr("Could not create a task object for importing appliance into VirtualBox")); 2376 } 2377 2378 if (FAILED(rc)) 2379 { 2380 if (ovfTask) 2381 delete ovfTask; 2382 if (cloudTask) 2383 delete cloudTask; 2384 throw rc; 2385 } 2006 2386 2007 2387 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.