VirtualBox

Changeset 90220 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 16, 2021 1:37:04 AM (4 years ago)
Author:
vboxsync
Message:

VBoxManage: cloud machine - handle cloud's --provider/--profile
options early. Try to be user friendly and don't insist on specifying
the options when there's only a single provider/profile present.
Start a very rudimentary implementation of "list". bugref:10065.

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
2 edited

Legend:

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

    r90214 r90220  
    4747 * this file less crowded.
    4848 */
    49 RTEXITCODE handleCloudMachine(HandlerArg *a, int iFirst, const ComPtr<ICloudProfile> &pCloudProfile);
    50 RTEXITCODE listCloudMachines(HandlerArg *a, int iFirst, const ComPtr<ICloudProfile> &pCloudProfile);
     49RTEXITCODE handleCloudMachine(HandlerArg *a, int iFirst,
     50                              const char *pszProviderName,
     51                              const char *pszProfileName);
     52RTEXITCODE listCloudMachines(HandlerArg *a, int iFirst,
     53                              const char *pszProviderName,
     54                              const char *pszProfileName);
    5155
    5256
     
    489493            case 1008:          /* machines */
    490494                return listCloudMachines(a, GetState.iNext,
    491                                          pCommonOpts->profile.pCloudProfile);
     495                                         pCommonOpts->provider.pszProviderName,
     496                                         pCommonOpts->profile.pszProfileName);
    492497
    493498            case VINF_GETOPT_NOT_OPTION:
     
    27972802            case 1006:
    27982803                return handleCloudMachine(a, GetState.iNext,
    2799                                           commonOpts.profile.pCloudProfile);
     2804                                          commonOpts.provider.pszProviderName,
     2805                                          commonOpts.profile.pszProfileName);
    28002806
    28012807            case VINF_GETOPT_NOT_OPTION:
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageCloudMachine.cpp

    r90219 r90220  
    2525
    2626
    27 RTEXITCODE listCloudMachines(HandlerArg *a, int iFirst, const ComPtr<ICloudProfile> &pCloudProfile);
     27static int selectCloudProvider(ComPtr<ICloudProvider> &pProvider,
     28                               const ComPtr<IVirtualBox> &pVirtualBox,
     29                               const char *pszProviderName);
     30static int selectCloudProfile(ComPtr<ICloudProfile> &pProfile,
     31                              const ComPtr<ICloudProvider> &pProvider,
     32                              const char *pszProviderName);
     33
     34static RTEXITCODE handleCloudMachineImpl(HandlerArg *a, int iFirst,
     35                                         const ComPtr<ICloudProfile> &pProfile);
     36static RTEXITCODE listCloudMachinesImpl(HandlerArg *a, int iFirst,
     37                                        const ComPtr<ICloudProfile> &pProfile);
     38
     39
     40
     41/*
     42 * This is a temporary hack as I don't want to refactor "cloud"
     43 * handling right now, as it's not yet clear to me what is the
     44 * direction that we want to take with it.
     45 *
     46 * The problem with the way "cloud" command handling is currently
     47 * written is that it's a bit schizophrenic about whether we have
     48 * multiple cloud providers or not.  OTOH it insists on --provider
     49 * being mandatory, on the other it hardcodes the list of available
     50 * subcommands, though in principle those can vary from provider to
     51 * provider.  If we do want to support multiple providers we might
     52 * need to come up with a way to allow an extpack provider to supply
     53 * its own VBoxManage command handler for "cloud" based on --provider
     54 * as the selector.
     55 *
     56 * Processing of --provider and --profile should not be postponed
     57 * until the leaf command handler, but rather happen immediately, so
     58 * do this here at our earliest opportunity (without actually doing it
     59 * in handleCloud).
     60 */
     61RTEXITCODE
     62handleCloudMachine(HandlerArg *a, int iFirst,
     63                   const char *pcszProviderName,
     64                   const char *pcszProfileName)
     65{
     66    int rc;
     67
     68    ComPtr<ICloudProvider> pProvider;
     69    rc = selectCloudProvider(pProvider, a->virtualBox, pcszProviderName);
     70    if (RT_FAILURE(rc))
     71        return RTEXITCODE_FAILURE;
     72
     73    ComPtr<ICloudProfile> pProfile;
     74    rc = selectCloudProfile(pProfile, pProvider, pcszProfileName);
     75    if (RT_FAILURE(rc))
     76        return RTEXITCODE_FAILURE;
     77
     78    return handleCloudMachineImpl(a, iFirst, pProfile);
     79}
     80
     81
     82/*
     83 * Select cloud provider to use based on the --provider option to the
     84 * "cloud" command.  The option is not mandatory if only a single
     85 * provider is available.
     86 */
     87static int
     88selectCloudProvider(ComPtr<ICloudProvider> &pProvider,
     89                    const ComPtr<IVirtualBox> &pVirtualBox,
     90                    const char *pcszProviderName)
     91{
     92    HRESULT hrc;
     93
     94    ComPtr<ICloudProviderManager> pCloudProviderManager;
     95    CHECK_ERROR2_RET(hrc, pVirtualBox,
     96        COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
     97            VERR_GENERAL_FAILURE);
     98
     99
     100    /*
     101     * If the provider is explicitly specified, just look it up and
     102     * return.
     103     */
     104    if (pcszProviderName != NULL)
     105    {
     106        /*
     107         * Should we also provide a way to specify the provider also
     108         * by its id?  Is it even useful?  If so, should we use a
     109         * different option or check if the provider name looks like
     110         * an id and used a different getter?
     111         */
     112        CHECK_ERROR2_RET(hrc, pCloudProviderManager,
     113            GetProviderByShortName(com::Bstr(pcszProviderName).raw(),
     114                                   pProvider.asOutParam()),
     115                VERR_NOT_FOUND);
     116
     117        return VINF_SUCCESS;
     118    }
     119
     120
     121    /*
     122     * We have only one provider and it's not clear if we will ever
     123     * have more than one.  Forcing the user to explicitly specify the
     124     * only provider available is not very nice.  So try to be
     125     * friendly.
     126     */
     127    com::SafeIfaceArray<ICloudProvider> aProviders;
     128    CHECK_ERROR2_RET(hrc, pCloudProviderManager,
     129        COMGETTER(Providers)(ComSafeArrayAsOutParam(aProviders)),
     130            VERR_GENERAL_FAILURE);
     131
     132    if (aProviders.size() == 0)
     133    {
     134        RTMsgError("cloud: no providers available");
     135        return VERR_NOT_FOUND;
     136    }
     137
     138    if (aProviders.size() > 1)
     139    {
     140        RTMsgError("cloud: multiple providers available,"
     141                   " '--provider' option is required");
     142        return VERR_MISSING;
     143    }
     144
     145    /* Do RTMsgInfo telling the user which one was selected? */
     146    pProvider = aProviders[0];
     147    return VINF_SUCCESS;
     148}
     149
     150
     151/*
     152 * Select cloud profile to use based on the --profile option to the
     153 * "cloud" command.  The option is not mandatory if only a single
     154 * profile exists.
     155 */
     156static int
     157selectCloudProfile(ComPtr<ICloudProfile> &pProfile,
     158                   const ComPtr<ICloudProvider> &pProvider,
     159                   const char *pcszProfileName)
     160{
     161    HRESULT hrc;
     162
     163    /*
     164     * If the profile is explicitly specified, just look it up and
     165     * return.
     166     */
     167    if (pcszProfileName != NULL)
     168    {
     169        CHECK_ERROR2_RET(hrc, pProvider,
     170            GetProfileByName(com::Bstr(pcszProfileName).raw(),
     171                             pProfile.asOutParam()),
     172                VERR_NOT_FOUND);
     173
     174        return VINF_SUCCESS;
     175    }
     176
     177
     178    /*
     179     * If the user has just one profile for this provider, don't force
     180     * them to specify it.  I'm not entirely sure about this one,
     181     * actually.  It's nice for interactive use, but it might be not
     182     * forward compatible if used in a script and then when another
     183     * profile is created the script starts failing.  I'd say, give
     184     * them enough rope...
     185     */
     186    com::SafeIfaceArray<ICloudProfile> aProfiles;
     187    CHECK_ERROR2_RET(hrc, pProvider,
     188        COMGETTER(Profiles)(ComSafeArrayAsOutParam(aProfiles)),
     189            VERR_GENERAL_FAILURE);
     190
     191    if (aProfiles.size() == 0)
     192    {
     193        RTMsgError("cloud: no profiles exist");
     194        return VERR_NOT_FOUND;
     195    }
     196
     197    if (aProfiles.size() > 1)
     198    {
     199        RTMsgError("cloud: multiple profiles exist,"
     200                   " '--profile' option is required");
     201        return VERR_MISSING;
     202    }
     203
     204    /* Do RTMsgInfo telling the user which one was selected? */
     205    pProfile = aProfiles[0];
     206    return VINF_SUCCESS;
     207}
    28208
    29209
     
    41221
    42222/*
    43  * VBoxManage cloud machine ...
     223 * cloud machine ...
    44224 *
    45225 * The "cloud" prefix handling is in VBoxManageCloud.cpp, so this
    46226 * function is not static.
    47227 */
    48 RTEXITCODE handleCloudMachine(HandlerArg *a, int iFirst,
    49                               const ComPtr<ICloudProfile> &pCloudProfile)
    50 {
     228static RTEXITCODE
     229handleCloudMachineImpl(HandlerArg *a, int iFirst,
     230                       const ComPtr<ICloudProfile> &pProfile)
     231{
     232    /*
     233     * cloud machine ...
     234     */
    51235    enum
    52236    {
     
    64248
    65249    int rc;
     250
     251    // setCurrentSubcommand(...);
    66252
    67253    RTGETOPTSTATE OptState;
     
    84270
    85271            case kMachine_List:
    86                 return listCloudMachines(a, OptState.iNext, pCloudProfile);
     272                return listCloudMachinesImpl(a, OptState.iNext, pProfile);
    87273
    88274
     
    108294
    109295/*
    110  * VBoxManage cloud list machines
    111  * VBoxManage cloud machine list # convenience alias
     296 * cloud list machines
    112297 *
    113298 * The "cloud list" prefix handling is in VBoxManageCloud.cpp, so this
    114  * function is not static.
    115  */
    116 RTEXITCODE listCloudMachines(HandlerArg *a, int iFirst,
    117                              const ComPtr<ICloudProfile> &pCloudProfile)
    118 {
    119     RT_NOREF(a, iFirst, pCloudProfile);
    120 
    121     return RTMsgErrorExit(RTEXITCODE_FAILURE,
    122                "cloud list machines - not yet implemented");
    123 }
     299 * function is not static.  See handleCloudMachine() for the
     300 * explanation early provider/profile lookup.
     301 */
     302RTEXITCODE
     303listCloudMachines(HandlerArg *a, int iFirst,
     304                  const char *pcszProviderName,
     305                  const char *pcszProfileName)
     306{
     307    int rc;
     308
     309    ComPtr<ICloudProvider> pProvider;
     310    rc = selectCloudProvider(pProvider, a->virtualBox, pcszProviderName);
     311    if (RT_FAILURE(rc))
     312        return RTEXITCODE_FAILURE;
     313
     314    ComPtr<ICloudProfile> pProfile;
     315    rc = selectCloudProfile(pProfile, pProvider, pcszProfileName);
     316    if (RT_FAILURE(rc))
     317        return RTEXITCODE_FAILURE;
     318
     319    return listCloudMachinesImpl(a, iFirst, pProfile);
     320}
     321
     322
     323/*
     324 * cloud machine list   # convenience alias
     325 * cloud list machines  # see above
     326 */
     327static RTEXITCODE
     328listCloudMachinesImpl(HandlerArg *a, int iFirst,
     329                      const ComPtr<ICloudProfile> &pProfile)
     330{
     331    /*
     332     * cloud machine list
     333     */
     334    static const RTGETOPTDEF s_aOptions[] =
     335    {
     336        { "--long",         'l',                    RTGETOPT_REQ_NOTHING },
     337        { "--short",        's',                    RTGETOPT_REQ_NOTHING },
     338          CLOUD_MACHINE_RTGETOPTDEF_HELP
     339    };
     340
     341    enum kFormatEnum
     342    {
     343        kFormat_Default,
     344        kFormat_Short,
     345        kFormat_Long
     346    };
     347
     348    HRESULT hrc;
     349    int rc;
     350
     351    kFormatEnum enmFormat = kFormat_Default;
     352
     353
     354    RTGETOPTSTATE OptState;
     355    rc = RTGetOptInit(&OptState, a->argc, a->argv,
     356                      s_aOptions, RT_ELEMENTS(s_aOptions),
     357                      iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
     358    AssertRCStmt(rc,
     359        return RTMsgErrorExit(RTEXITCODE_INIT, /* internal error */
     360                   "cloud machine list: RTGetOptInit: %Rra", rc));
     361
     362    int ch;
     363    RTGETOPTUNION Val;
     364    while ((ch = RTGetOpt(&OptState, &Val)) != 0)
     365    {
     366        switch (ch)
     367        {
     368            case 'l':
     369                enmFormat = kFormat_Long;
     370                break;
     371
     372            case 's':
     373                enmFormat = kFormat_Short;
     374                break;
     375
     376            case 'h':           /* --help */
     377                printHelp(g_pStdOut);
     378                return RTEXITCODE_SUCCESS;
     379
     380
     381            case VINF_GETOPT_NOT_OPTION:
     382                return RTMsgErrorExit(RTEXITCODE_SYNTAX,
     383                           "Invalid sub-command: %s", Val.psz);
     384
     385            default:
     386                return RTGetOptPrintError(ch, &Val);
     387        }
     388    }
     389
     390    ComPtr<ICloudClient> pClient;
     391    CHECK_ERROR2_RET(hrc, pProfile,
     392        CreateCloudClient(pClient.asOutParam()),
     393            RTEXITCODE_FAILURE);
     394
     395    ComPtr<IProgress> pListProgress;
     396    CHECK_ERROR2_RET(hrc, pClient,
     397        ReadCloudMachineList(pListProgress.asOutParam()),
     398            RTEXITCODE_FAILURE);
     399
     400    hrc = showProgress(pListProgress); // XXX: don't show
     401    if (FAILED(hrc))
     402        return RTEXITCODE_FAILURE;
     403
     404    com::SafeIfaceArray<ICloudMachine> aMachines;
     405    CHECK_ERROR2_RET(hrc, pClient,
     406        COMGETTER(CloudMachineList)(ComSafeArrayAsOutParam(aMachines)),
     407            RTEXITCODE_FAILURE);
     408
     409    for (size_t i = 0; i < aMachines.size(); ++i)
     410    {
     411        const ComPtr<ICloudMachine> pMachine = aMachines[i];
     412
     413        com::Bstr bstrId;
     414        CHECK_ERROR2_RET(hrc, pMachine,
     415            COMGETTER(Id)(bstrId.asOutParam()),
     416                RTEXITCODE_FAILURE);
     417
     418        com::Bstr bstrName;
     419        CHECK_ERROR2_RET(hrc, pMachine,
     420            COMGETTER(Name)(bstrName.asOutParam()),
     421                RTEXITCODE_FAILURE);
     422
     423        RTPrintf("%ls %ls\n", bstrId.raw(), bstrName.raw());
     424    }
     425
     426    return RTEXITCODE_SUCCESS;
     427}
Note: See TracChangeset for help on using the changeset viewer.

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