VirtualBox

Changeset 78428 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 7, 2019 11:03:49 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
130427
Message:

bugref:9416. The part of OCI import logic. New functions - OciRestClient::exportImage, createImageFromInstance; new API functions - ICloudClient::importInstance, getInstanceInfo; new helper classes - HandleRestBinaryResponse, DownloadSession; changes in the Appliance import and export parts.

Location:
trunk/src/VBox
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp

    r76553 r78428  
    146146    { "--disk",                 'D', RTGETOPT_REQ_STRING },
    147147    { "--options",              'O', RTGETOPT_REQ_STRING },
     148
     149    { "--cloud",                'j', RTGETOPT_REQ_NOTHING},
     150    { "--cloudprofile",         'k', RTGETOPT_REQ_STRING },
     151    { "--cloudinstanceid",      'l', RTGETOPT_REQ_STRING }
    148152};
     153
     154enum
     155{
     156    NOT_SET, LOCAL, CLOUD
     157} actionType;
    149158
    150159RTEXITCODE handleImportAppliance(HandlerArg *arg)
    151160{
    152161    HRESULT rc = S_OK;
    153 
     162    bool fCloud = false; // the default
     163    actionType = NOT_SET;
    154164    Utf8Str strOvfFilename;
    155165    bool fExecute = true;                  // if true, then we actually do the import
     
    182192
    183193            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
    184202                ulCurVsys = ValueUnion.u32;
    185203                ulCurUnit = (uint32_t)-1;
     
    187205
    188206            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);
    191209                mapArgsMapsPerVsys[ulCurVsys]["ostype"] = ValueUnion.psz;
    192210                break;
    193211
    194212            case 'V':   // --vmname
    195                 if (ulCurVsys == (uint32_t)-1)
     213                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    196214                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    197215                mapArgsMapsPerVsys[ulCurVsys]["vmname"] = ValueUnion.psz;
     
    199217
    200218            case 'S':   // --settingsfile
    201                 if (ulCurVsys == (uint32_t)-1)
     219                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    202220                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    203221                mapArgsMapsPerVsys[ulCurVsys]["settingsfile"] = ValueUnion.psz;
     
    205223
    206224            case 'p':   // --basefolder
    207                 if (ulCurVsys == (uint32_t)-1)
     225                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    208226                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    209227                mapArgsMapsPerVsys[ulCurVsys]["basefolder"] = ValueUnion.psz;
     
    211229
    212230            case 'g':   // --group
    213                 if (ulCurVsys == (uint32_t)-1)
     231                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    214232                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    215233                mapArgsMapsPerVsys[ulCurVsys]["group"] = ValueUnion.psz;
     
    217235
    218236            case 'd':   // --description
    219                 if (ulCurVsys == (uint32_t)-1)
     237                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    220238                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    221239                mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz;
     
    223241
    224242            case 'L':   // --eula
    225                 if (ulCurVsys == (uint32_t)-1)
     243                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    226244                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    227245                mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz;
     
    229247
    230248            case 'm':   // --memory
    231                 if (ulCurVsys == (uint32_t)-1)
     249                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    232250                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    233251                mapArgsMapsPerVsys[ulCurVsys]["memory"] = ValueUnion.psz;
     
    235253
    236254            case 'c':   // --cpus
    237                 if (ulCurVsys == (uint32_t)-1)
     255                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    238256                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    239257                mapArgsMapsPerVsys[ulCurVsys]["cpus"] = ValueUnion.psz;
     
    245263
    246264            case 'x':   // --ignore
    247                 if (ulCurVsys == (uint32_t)-1)
     265                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    248266                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    249267                if (ulCurUnit == (uint32_t)-1)
     
    253271
    254272            case 'T':   // --scsitype
    255                 if (ulCurVsys == (uint32_t)-1)
     273                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    256274                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    257275                if (ulCurUnit == (uint32_t)-1)
     
    261279
    262280            case 'C':   // --controller
    263                 if (ulCurVsys == (uint32_t)-1)
     281                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    264282                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    265283                if (ulCurUnit == (uint32_t)-1)
     
    269287
    270288            case 'D':   // --disk
    271                 if (ulCurVsys == (uint32_t)-1)
     289                if (actionType == LOCAL && ulCurVsys == (uint32_t)-1)
    272290                    return errorSyntax(USAGE_IMPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    273291                if (ulCurUnit == (uint32_t)-1)
     
    279297                if (RT_FAILURE(parseImportOptions(ValueUnion.psz, &options)))
    280298                    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;
    281330                break;
    282331
     
    305354    }
    306355
    307     if (strOvfFilename.isEmpty())
     356    if (actionType == LOCAL && strOvfFilename.isEmpty())
    308357        return errorSyntax(USAGE_IMPORTAPPLIANCE, "Not enough arguments for \"import\" command.");
    309358
     
    313362        CHECK_ERROR_BREAK(arg->virtualBox, CreateAppliance(pAppliance.asOutParam()));
    314363
     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
    315376        char *pszAbsFilePath;
    316377        if (strOvfFilename.startsWith("S3://", RTCString::CaseInsensitive) ||
    317378            strOvfFilename.startsWith("SunCloud://", RTCString::CaseInsensitive) ||
    318             strOvfFilename.startsWith("webdav://", RTCString::CaseInsensitive))
     379            strOvfFilename.startsWith("webdav://", RTCString::CaseInsensitive) ||
     380            strOvfFilename.startsWith("OCI://", RTCString::CaseInsensitive))
    319381            pszAbsFilePath = RTStrDup(strOvfFilename.c_str());
    320382        else
    321383            pszAbsFilePath = RTPathAbsDup(strOvfFilename.c_str());
     384
    322385        ComPtr<IProgress> progressRead;
    323386        CHECK_ERROR_BREAK(pAppliance, Read(Bstr(pszAbsFilePath).raw(),
     
    330393        Bstr path; /* fetch the path, there is stuff like username/password removed if any */
    331394        CHECK_ERROR_BREAK(pAppliance, COMGETTER(Path)(path.asOutParam()));
    332         // call interpret(); this can yield both warnings and errors, so we need
    333         // to tinker with the error info a bit
    334         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 warnings
    350         {
    351             com::GluePrintErrorInfo(info0);
    352             com::GluePrintErrorContext("Interpret", __FILE__, __LINE__);
    353             break;
    354         }
    355 
    356         RTStrmPrintf(g_pStdErr, "OK.\n");
    357 
    358         // fetch all disks
    359         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         }
    369395
    370396        // fetch virtual system descriptions
     
    375401        size_t cVirtualSystemDescriptions = aVirtualSystemDescriptions.size();
    376402
    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)
    383404        {
    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            }
    389456        }
    390457
     
    920987                        case VirtualSystemDescriptionType_CloudKeepObject:
    921988                        case VirtualSystemDescriptionType_CloudLaunchInstance:
     989                        case VirtualSystemDescriptionType_CloudInstanceId:
     990                        case VirtualSystemDescriptionType_CloudImageId:
    922991                        case VirtualSystemDescriptionType_Miscellaneous:
    923992                            /** @todo  VirtualSystemDescriptionType_Miscellaneous? */
     
    10411110};
    10421111
    1043 enum
    1044 {
    1045     NOT_SET, LOCAL, CLOUD
    1046 } exportType;
    1047 
    10481112RTEXITCODE handleExportAppliance(HandlerArg *a)
    10491113{
     
    10541118    bool fManifest = false; // the default
    10551119    bool fCloud = false; // the default
    1056     exportType = NOT_SET;
     1120    actionType = NOT_SET;
    10571121    bool fExportISOImages = false; // the default
    10581122    com::SafeArray<ExportOptions_T> options;
     
    11091173
    11101174                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)
    11151179                        return errorSyntax(USAGE_EXPORTAPPLIANCE,
    11161180                                           "Option \"%s\" can't be used together with \"--cloud\" argument.",
     
    11211185
    11221186                case 'V':   // --vmname
    1123                     if (exportType == NOT_SET || ulCurVsys == (uint32_t)-1)
     1187                    if (actionType == NOT_SET || ulCurVsys == (uint32_t)-1)
    11241188                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys or --cloud argument.",
    11251189                                           GetState.pDef->pszLong);
     
    11281192
    11291193                case 'p':   // --product
    1130                     if (exportType != LOCAL)
     1194                    if (actionType != LOCAL)
    11311195                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11321196                    mapArgsMapsPerVsys[ulCurVsys]["product"] = ValueUnion.psz;
     
    11341198
    11351199                case 'P':   // --producturl
    1136                     if (exportType != LOCAL)
     1200                    if (actionType != LOCAL)
    11371201                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11381202                    mapArgsMapsPerVsys[ulCurVsys]["producturl"] = ValueUnion.psz;
     
    11401204
    11411205                case 'n':   // --vendor
    1142                     if (exportType != LOCAL)
     1206                    if (actionType != LOCAL)
    11431207                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11441208                    mapArgsMapsPerVsys[ulCurVsys]["vendor"] = ValueUnion.psz;
     
    11461210
    11471211                case 'N':   // --vendorurl
    1148                     if (exportType != LOCAL)
     1212                    if (actionType != LOCAL)
    11491213                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11501214                    mapArgsMapsPerVsys[ulCurVsys]["vendorurl"] = ValueUnion.psz;
     
    11521216
    11531217                case 'v':   // --version
    1154                     if (exportType != LOCAL)
     1218                    if (actionType != LOCAL)
    11551219                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11561220                    mapArgsMapsPerVsys[ulCurVsys]["version"] = ValueUnion.psz;
     
    11581222
    11591223                case 'd':   // --description
    1160                     if (exportType != LOCAL)
     1224                    if (actionType != LOCAL)
    11611225                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11621226                    mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz;
     
    11641228
    11651229                case 'e':   // --eula
    1166                     if (exportType != LOCAL)
     1230                    if (actionType != LOCAL)
    11671231                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11681232                    mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz;
     
    11701234
    11711235                case 'E':   // --eulafile
    1172                     if (exportType != LOCAL)
     1236                    if (actionType != LOCAL)
    11731237                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --vsys argument.", GetState.pDef->pszLong);
    11741238                    mapArgsMapsPerVsys[ulCurVsys]["eulafile"] = ValueUnion.psz;
     
    11821246                    /*--cloud and --vsys are orthogonal, only one must be presented*/
    11831247                case 'C':   // --cloud
    1184                     if (fCloud == false && exportType == NOT_SET)
     1248                    if (fCloud == false && actionType == NOT_SET)
    11851249                    {
    11861250                        fCloud = true;
    1187                         exportType = CLOUD;
     1251                        actionType = CLOUD;
    11881252                    }
    11891253
    1190                     if (exportType != CLOUD)
     1254                    if (actionType != CLOUD)
    11911255                        return errorSyntax(USAGE_EXPORTAPPLIANCE,
    11921256                                           "Option \"%s\" can't be used together with \"--vsys\" argument.",
     
    11981262                    /* Cloud export settings */
    11991263                case 'S':   // --cloudshape
    1200                     if (exportType != CLOUD)
     1264                    if (actionType != CLOUD)
    12011265                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12021266                                           GetState.pDef->pszLong);
     
    12051269
    12061270                case 'D':   // --clouddomain
    1207                     if (exportType != CLOUD)
     1271                    if (actionType != CLOUD)
    12081272                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12091273                                           GetState.pDef->pszLong);
     
    12121276
    12131277                case 'R':   // --clouddisksize
    1214                     if (exportType != CLOUD)
     1278                    if (actionType != CLOUD)
    12151279                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12161280                                           GetState.pDef->pszLong);
     
    12191283
    12201284                case 'B':   // --cloudbucket
    1221                     if (exportType != CLOUD)
     1285                    if (actionType != CLOUD)
    12221286                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12231287                                           GetState.pDef->pszLong);
     
    12261290
    12271291                case 'Q':   // --cloudocivcn
    1228                     if (exportType != CLOUD)
     1292                    if (actionType != CLOUD)
    12291293                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12301294                                           GetState.pDef->pszLong);
     
    12331297
    12341298                case 'A':   // --cloudpublicip
    1235                     if (exportType != CLOUD)
     1299                    if (actionType != CLOUD)
    12361300                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12371301                                           GetState.pDef->pszLong);
     
    12401304
    12411305                case 'F':   // --cloudprofile
    1242                     if (exportType != CLOUD)
     1306                    if (actionType != CLOUD)
    12431307                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12441308                                           GetState.pDef->pszLong);
     
    12471311
    12481312                case 'T':   // --cloudocisubnet
    1249                     if (exportType != CLOUD)
     1313                    if (actionType != CLOUD)
    12501314                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12511315                                           GetState.pDef->pszLong);
     
    12541318
    12551319                case 'K':   // --cloudkeepobject
    1256                     if (exportType != CLOUD)
     1320                    if (actionType != CLOUD)
    12571321                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12581322                                           GetState.pDef->pszLong);
     
    12611325
    12621326                case 'L':   // --cloudlaunchinstance
    1263                     if (exportType != CLOUD)
     1327                    if (actionType != CLOUD)
    12641328                        return errorSyntax(USAGE_EXPORTAPPLIANCE, "Option \"%s\" requires preceding --cloud argument.",
    12651329                                           GetState.pDef->pszLong);
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r78351 r78428  
    36273627  <enum
    36283628    name="VirtualSystemDescriptionType"
    3629     uuid="425d0e49-eb9c-43e8-bb0d-be7f78fd3b47"
     3629    uuid="48875667-19f6-4329-a208-735adf9a47ee"
    36303630    >
    36313631    <desc>Used with <link to="IVirtualSystemDescription" /> to describe the type of
     
    36823682    <const name="CloudKeepObject" value="35" />
    36833683    <const name="CloudLaunchInstance" value="36" />
     3684    <const name="CloudInstanceId" value="37" />
     3685    <const name="CloudImageId" value="38" />
    36843686  </enum>
    36853687
     
    2574025742    name="ICloudClient" extends="$unknown"
    2574125743    uuid="7acc426a-5f8f-11e9-9032-1b0da54759a8"
    25742     wsmap="managed" reservedMethods="13" reservedAttributes="8"
     25744    wsmap="managed" reservedMethods="11" reservedAttributes="8"
    2574325745    >
    2574425746
     
    2581925821          Progress object to track the operation completion.
    2582025822        </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>
    2582125853      </param>
    2582225854    </method>
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r78255 r78428  
    102102    HRESULT createVFSExplorer(const com::Utf8Str &aURI,
    103103                              ComPtr<IVFSExplorer> &aExplorer);
    104     HRESULT createVirtualSystemDescriptions(ULONG aRequested, ULONG *aCreated);
    105104    HRESULT write(const com::Utf8Str &aFormat,
    106105                  const std::vector<ExportOptions_T> &aOptions,
     
    112111    HRESULT addPasswords(const std::vector<com::Utf8Str> &aIdentifiers,
    113112                         const std::vector<com::Utf8Str> &aPasswords);
    114 
     113    HRESULT createVirtualSystemDescriptions(ULONG aRequested, ULONG *aCreated);
    115114    /** weak VirtualBox parent */
    116115    VirtualBox* const mVirtualBox;
     
    124123    Data *m;
    125124
    126     enum SetUpProgressMode { ImportFile, ImportS3, WriteFile, WriteS3, ExportCloud };
     125    enum SetUpProgressMode { ImportFile, ImportS3, WriteFile, WriteS3, ExportCloud, ImportCloud };
    127126
    128127    /** @name General stuff
     
    143142    static void i_importOrExportThreadTask(TaskOVF *pTask);
    144143    static void i_exportOPCThreadTask(TaskOPC *pTask);
    145     static void i_exportCloudThreadTask(TaskCloud *pTask);
     144    static void i_importOrExportCloudThreadTask(TaskCloud *pTask);
    146145
    147146    HRESULT i_initBackendNames();
     
    171170    HRESULT i_readSignatureFile(TaskOVF *pTask, RTVFSIOSTREAM hIosCert, const char *pszSubFileNm);
    172171    HRESULT i_readTailProcessing(TaskOVF *pTask);
     172    HRESULT i_gettingCloudData(TaskCloud *pTask);
     173
    173174    /** @}  */
    174175
     
    215216    void    i_importDecompressFile(ImportStack &stack, Utf8Str const &rstrSrcPath, Utf8Str const &rstrDstPath,
    216217                                   const char *pszManifestEntry);
     218    HRESULT i_importCloudImpl(TaskCloud *pTask);
    217219    /** @} */
    218220
     
    228230    HRESULT i_writeFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock);
    229231    HRESULT i_writeFSOPC(TaskOPC *pTask);
    230     HRESULT i_writeFSCloud(TaskCloud *pTask);
     232    HRESULT i_exportCloudImpl(TaskCloud *pTask);
    231233    HRESULT i_writeFSImpl(TaskOVF *pTask, AutoWriteLockBase &writeLock, RTVFSFSSTREAM hVfsFssDst);
    232234    HRESULT i_writeBufferToFile(RTVFSFSSTREAM hVfsFssDst, const char *pszFilename, const void *pvContent, size_t cbContent);
  • trunk/src/VBox/Main/include/ApplianceImplPrivate.h

    r76562 r78428  
    339339    enum TaskType
    340340    {
    341         Export
     341        Export,
     342        Import,
     343        ReadData
    342344    };
    343345
     
    353355        rc(S_OK)
    354356    {
    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        }
    356364    }
    357365
     
    371379    void handler()
    372380    {
    373         Appliance::i_exportCloudThreadTask(this);
     381        Appliance::i_importOrExportCloudThreadTask(this);
    374382    }
    375383};
  • trunk/src/VBox/Main/src-server/ApplianceImpl.cpp

    r78256 r78428  
    11041104        }
    11051105        case ExportCloud:
    1106             cOperations = 1 + 9;//7
    1107             ulTotalOperationsWeight = 100*cOperations;
    1108             m->ulWeightForXmlOperation = 100;
     1106        case ImportCloud:
    11091107            break;
    11101108    }
     
    13401338 */
    13411339/* static */
    1342 void Appliance::i_exportCloudThreadTask(TaskCloud *pTask)
     1340void Appliance::i_importOrExportCloudThreadTask(TaskCloud *pTask)
    13431341{
    13441342    LogFlowFuncEnter();
     
    13511349    {
    13521350        case TaskCloud::Export:
    1353             pTask->rc = pAppliance->i_writeFSCloud(pTask);
     1351            pTask->rc = pAppliance->i_exportCloudImpl(pTask);
    13541352            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;
    13561359        default:
    13571360            AssertFailed();
     
    14111414
    14121415    /* Not necessary on a file based URI */
    1413     if (locInfo.storageType != VFSType_File)
    1414     {
    1415         size_t uppos = strUri.find("@"); /* username:password combo */
    1416         if (uppos != Utf8Str::npos)
    1417         {
    1418             locInfo.strUsername = strUri.substr(0, uppos);
    1419             strUri = strUri.substr(uppos + 1);
    1420             size_t upos = locInfo.strUsername.find(":");
    1421             if (upos != Utf8Str::npos)
    1422             {
    1423                 locInfo.strPassword = locInfo.strUsername.substr(upos + 1);
    1424                 locInfo.strUsername = locInfo.strUsername.substr(0, upos);
    1425             }
    1426         }
    1427         size_t hpos = strUri.find("/"); /* hostname part */
    1428         if (hpos != Utf8Str::npos)
    1429         {
    1430             locInfo.strHostname = strUri.substr(0, hpos);
    1431             strUri = strUri.substr(hpos);
    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//  }
    14341437
    14351438    locInfo.strPath = strUri;
  • trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp

    r76592 r78428  
    653653    i_parseURI(aPath, m->locInfo);
    654654
    655     if (m->locInfo.storageType == VFSType_Cloud)//(isCloudDestination(aPath))
     655    if (m->locInfo.storageType == VFSType_Cloud)
    656656    {
    657657        rc = S_OK;
     
    22422242 * instance with this image in the OCI Compute service.
    22432243 */
    2244 HRESULT Appliance::i_writeFSCloud(TaskCloud *pTask)
     2244HRESULT Appliance::i_exportCloudImpl(TaskCloud *pTask)
    22452245{
    22462246    LogFlowFuncEnter();
     
    22502250    hrc = mVirtualBox->COMGETTER(CloudProviderManager)(cpm.asOutParam());
    22512251    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__));
    22532253
    22542254    Utf8Str strProviderName = pTask->locInfo.strProvider;
     
    22582258
    22592259    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__));
    22612261
    22622262    ComPtr<IVirtualSystemDescription> vsd = m->virtualSystemDescriptions.front();
     
    22792279    Utf8Str profileName(aVBoxValues[0]);
    22802280    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__));
    22822282
    22832283    hrc = cloudProvider->GetProfileByName(aVBoxValues[0], cloudProfile.asOutParam());
    22842284    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__));
    22862286
    22872287    ComObjPtr<ICloudClient> cloudClient;
    22882288    hrc = cloudProfile->CreateCloudClient(cloudClient.asOutParam());
    22892289    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__));
    22932291
    22942292    if (m->virtualSystemDescriptions.size() == 1)
  • trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp

    r78104 r78428  
    8888    }
    8989
    90     // see if we can handle this file; for now we insist it has an ovf/ova extension
    91     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 
    9590    ComObjPtr<Progress> progress;
    9691    try
     
    9893        /* Parse all necessary info out of the URI */
    9994        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
    100102        i_readImpl(m->locInfo, progress);
    101103    }
     
    790792        return E_ACCESSDENIED;
    791793
    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)
    793796        return setError(E_FAIL,
    794797                        tr("Cannot import machines without reading it first (call read() before i_importMachines())"));
     
    11211124                             bstrDesc.raw(),
    11221125                             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 */);
    11231132    else
    11241133        /* 4/5 is downloading, 1/5 is reading */
     
    11341143
    11351144    /* Initialize our worker task */
    1136     TaskOVF *task = NULL;
     1145    TaskOVF *ovfTask = NULL;
     1146    TaskCloud *cloudTask = NULL;
    11371147    try
    11381148    {
    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    }
    11411166    catch (...)
    11421167    {
    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
     1182HRESULT 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 */
     1282HRESULT 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;
    11491483}
    11501484
     
    19812315    if (locInfo.storageType == VFSType_File)
    19822316        mode = ImportFile;
     2317    else if (locInfo.storageType == VFSType_Cloud)
     2318        mode = ImportCloud;
    19832319    else
    19842320        mode = ImportS3;
    19852321
    1986     rc = i_setUpProgress(progress,
    1987                          BstrFmt(tr("Importing appliance '%s'"), locInfo.strPath.c_str()),
    1988                          mode);
    1989     if (FAILED(rc)) throw rc;
    1990 
    19912322    /* Initialize our worker task */
    1992     TaskOVF* task = NULL;
     2323    TaskOVF* ovfTask = NULL;
     2324    TaskCloud* cloudTask = NULL;
    19932325    try
    19942326    {
    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    }
    20062386
    20072387    return rc;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette