VirtualBox

Changeset 91188 in vbox


Ignore:
Timestamp:
Sep 9, 2021 10:59:50 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
146842
Message:

VBoxManageCloudMachine: Refactor getopt code so that all the commands
that take a machine argument (most of them) can get by with less
boilerplate code. (A very early refactoring in preparation for this
was accidentally committed as r146825). bugref:10065.

File:
1 edited

Legend:

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

    r91175 r91188  
    4141static HRESULT getMachineList(com::SafeIfaceArray<ICloudMachine> &aMachines,
    4242                              const ComPtr<ICloudClient> &pClient);
     43
    4344static HRESULT getMachineById(ComPtr<ICloudMachine> &pMachineOut,
    4445                              const ComPtr<ICloudClient> &pClient,
     
    4748                                const ComPtr<ICloudClient> &pClient,
    4849                                const char *pcszName);
    49 static HRESULT getMachine(ComPtr<ICloudMachine> &pMachineOut,
    50                           const ComPtr<ICloudClient> &pClient,
    51                           const char *pcszWhatever);
     50static HRESULT getMachineByGuess(ComPtr<ICloudMachine> &pMachineOut,
     51                                 const ComPtr<ICloudClient> &pClient,
     52                                 const char *pcszWhatever);
     53
     54struct MachineSpec {
     55    const char *pcszSpec;
     56    enum { GUESS, ID, NAME } enmKind;
     57
     58    MachineSpec()
     59      : pcszSpec(NULL), enmKind(GUESS) {}
     60};
     61
     62static int checkMachineSpecArgument(MachineSpec &aMachineSpec,
     63                                    int ch, const RTGETOPTUNION &Val);
     64static HRESULT getMachineBySpec(ComPtr<ICloudMachine> &pMachineOut,
     65                                const ComPtr<ICloudClient> &pClient,
     66                                const MachineSpec &aMachineSpec);
    5267
    5368
     
    371386 */
    372387static HRESULT
    373 getMachine(ComPtr<ICloudMachine> &pMachineOut,
    374            const ComPtr<ICloudClient> &pClient,
    375            const char *pcszWhatever)
     388getMachineByGuess(ComPtr<ICloudMachine> &pMachineOut,
     389                  const ComPtr<ICloudClient> &pClient,
     390                  const char *pcszWhatever)
    376391{
    377392    ComPtr<ICloudMachine> pMachine;
     
    406421        { "-?",             'h',                    RTGETOPT_REQ_NOTHING }
    407422
     423static RTEXITCODE
     424errThereCanBeOnlyOne()
     425{
     426    return RTMsgErrorExit(RTEXITCODE_SYNTAX,
     427               "only one machine can be specified");
     428}
     429
     430
     431#define CLOUD_MACHINE_RTGETOPTDEF_MACHINE               \
     432        { "--id",       'i',    RTGETOPT_REQ_STRING },  \
     433        { "--name",     'n',    RTGETOPT_REQ_STRING }
     434
     435
     436/*
     437 * Almost all the cloud machine commands take a machine argument, so
     438 * factor out the code to fish it out from the command line.
     439 *
     440 * ch - option should be processed by the caller.
     441 * VINF_SUCCESS - option was processed.
     442 * VERR_PARSE_ERROR - RTEXITCODE_SYNTAX
     443 * Other IPRT errors - RTEXITCODE_FAILURE
     444 */
     445static int
     446checkMachineSpecArgument(MachineSpec &aMachineSpec,
     447                         int ch, const RTGETOPTUNION &Val)
     448{
     449    int rc;
     450
     451    switch (ch)
     452    {
     453        /*
     454         * Note that we don't used RTGETOPT_REQ_UUID here as it would
     455         * be too limiting.  First, we need the original string for
     456         * the API call, not the UUID, and second, if the UUID has bad
     457         * forward RTGetOptPrintError doesn't have access to the
     458         * option argument for the error message.  So do the format
     459         * check ourselves.
     460         */
     461        case 'i':               /* --id */
     462        {
     463            const char *pcszId = Val.psz;
     464
     465            if (aMachineSpec.pcszSpec != NULL)
     466            {
     467                errThereCanBeOnlyOne();
     468                return VERR_PARSE_ERROR;
     469            }
     470
     471            RTUUID Uuid;
     472            rc = RTUuidFromStr(&Uuid, pcszId);
     473            if (RT_FAILURE(rc))
     474            {
     475                RTMsgError("not a valid uuid: %s", pcszId);
     476                return VERR_PARSE_ERROR;
     477            }
     478
     479            aMachineSpec.pcszSpec = pcszId;
     480            aMachineSpec.enmKind = MachineSpec::ID;
     481            return VINF_SUCCESS;
     482        }
     483
     484        case 'n':               /* --name */
     485        {
     486            const char *pcszName = Val.psz;
     487
     488            if (aMachineSpec.pcszSpec != NULL)
     489            {
     490                errThereCanBeOnlyOne();
     491                return VERR_PARSE_ERROR;
     492            }
     493
     494            aMachineSpec.pcszSpec = pcszName;
     495            aMachineSpec.enmKind = MachineSpec::NAME;
     496            return VINF_SUCCESS;
     497        }
     498
     499        /*
     500         * Plain word (no dash/es).  This must name a machine, though
     501         * we have to guess whether it's an id or a name.
     502         */
     503        case VINF_GETOPT_NOT_OPTION:
     504        {
     505            const char *pcszNameOrId = Val.psz;
     506
     507            if (aMachineSpec.pcszSpec != NULL)
     508            {
     509                errThereCanBeOnlyOne();
     510                return VERR_PARSE_ERROR;
     511            }
     512
     513            aMachineSpec.pcszSpec = pcszNameOrId;
     514            aMachineSpec.enmKind = MachineSpec::GUESS;
     515            return VINF_SUCCESS;
     516        }
     517
     518        /* might as well do it here */
     519        case 'h':               /* --help */
     520        {
     521            printHelp(g_pStdOut);
     522            return VINF_CALLBACK_RETURN;
     523        }
     524    }
     525
     526    /* let the caller deal with it */
     527    return VINF_NOT_SUPPORTED;
     528}
     529
     530
     531static HRESULT
     532getMachineBySpec(ComPtr<ICloudMachine> &pMachineOut,
     533                 const ComPtr<ICloudClient> &pClient,
     534                 const MachineSpec &aMachineSpec)
     535{
     536    HRESULT hrc = E_FAIL;
     537
     538    if (aMachineSpec.pcszSpec == NULL)
     539    {
     540        RTMsgErrorExit(RTEXITCODE_SYNTAX, "machine not specified");
     541        return E_FAIL;
     542    }
     543
     544    if (aMachineSpec.pcszSpec[0] == '\0')
     545    {
     546        RTMsgError("machine name is empty");
     547        return E_FAIL;
     548    }
     549
     550    switch (aMachineSpec.enmKind)
     551    {
     552        case MachineSpec::ID:
     553            hrc = getMachineById(pMachineOut, pClient, aMachineSpec.pcszSpec);
     554            if (FAILED(hrc))
     555            {
     556                if (hrc == VBOX_E_OBJECT_NOT_FOUND)
     557                    RTMsgError("unable to find machine with id %s", aMachineSpec.pcszSpec);
     558                return hrc;
     559            }
     560            break;
     561
     562        case MachineSpec::NAME:
     563            hrc = getMachineByName(pMachineOut, pClient, aMachineSpec.pcszSpec);
     564            if (FAILED(hrc))
     565            {
     566                if (hrc == VBOX_E_OBJECT_NOT_FOUND)
     567                    RTMsgError("unable to find machine with name %s", aMachineSpec.pcszSpec);
     568                return hrc;
     569            }
     570            break;
     571
     572        case MachineSpec::GUESS:
     573            hrc = getMachineByGuess(pMachineOut, pClient, aMachineSpec.pcszSpec);
     574            if (FAILED(hrc))
     575            {
     576                if (hrc == VBOX_E_OBJECT_NOT_FOUND)
     577                    RTMsgError("unable to find machine %s", aMachineSpec.pcszSpec);
     578                return hrc;
     579            }
     580            break;
     581    }
     582
     583    /* switch was exhaustive (and successful) */
     584    AssertReturn(SUCCEEDED(hrc), E_FAIL);
     585    return S_OK;
     586}
     587
     588
     589
    408590
    409591/*
     
    417599                       const ComPtr<ICloudClient> &pClient)
    418600{
    419     /*
    420      * cloud machine ...
    421      */
     601    int rc;
     602
    422603    enum
    423604    {
     
    428609    };
    429610
     611    // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE);
    430612    static const RTGETOPTDEF s_aOptions[] =
    431     {
     613        {
    432614        { "console-history",    kMachine_ConsoleHistory,    RTGETOPT_REQ_NOTHING },
    433615        { "consolehistory",     kMachine_ConsoleHistory,    RTGETOPT_REQ_NOTHING },
    434616        { "info",               kMachine_Info,              RTGETOPT_REQ_NOTHING },
    435617        { "list",               kMachine_List,              RTGETOPT_REQ_NOTHING },
    436           CLOUD_MACHINE_RTGETOPTDEF_HELP
     618        CLOUD_MACHINE_RTGETOPTDEF_HELP
    437619    };
    438 
    439     int rc;
    440 
    441     // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE);
    442620
    443621    RTGETOPTSTATE OptState;
     
    445623                      s_aOptions, RT_ELEMENTS(s_aOptions),
    446624                      iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    447     AssertRCStmt(rc,
    448         return RTMsgErrorExit(RTEXITCODE_INIT, /* internal error */
    449                    "cloud machine: RTGetOptInit: %Rra", rc));
     625    AssertRCReturn(rc, RTMsgErrorExit(RTEXITCODE_INIT,
     626                           "cloud machine: RTGetOptInit: %Rra", rc));
    450627
    451628    int ch;
     
    516693                      const ComPtr<ICloudClient> &pClient)
    517694{
    518     /*
    519      * cloud machine list
    520      */
     695    HRESULT hrc;
     696    int rc;
     697
     698    // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_LIST);
    521699    static const RTGETOPTDEF s_aOptions[] =
    522700    {
    523701        { "--long",         'l',                    RTGETOPT_REQ_NOTHING },
    524702        { "--sort",         's',                    RTGETOPT_REQ_NOTHING },
    525           CLOUD_MACHINE_RTGETOPTDEF_HELP
     703        CLOUD_MACHINE_RTGETOPTDEF_HELP
    526704    };
    527705
     
    531709    enum kSortOrderEnum { kSortOrder_None, kSortOrder_Name, kSortOrder_Id };
    532710    kSortOrderEnum enmSortOrder = kSortOrder_None;
    533 
    534     HRESULT hrc;
    535     int rc;
    536 
    537     // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_LIST);
    538711
    539712    RTGETOPTSTATE OptState;
     
    541714                      s_aOptions, RT_ELEMENTS(s_aOptions),
    542715                      iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    543     AssertRCStmt(rc,
    544         return RTMsgErrorExit(RTEXITCODE_INIT, /* internal error */
    545                    "cloud machine list: RTGetOptInit: %Rra", rc));
     716    AssertRCReturn(rc, RTMsgErrorExit(RTEXITCODE_INIT,
     717                           "cloud machine list: RTGetOptInit: %Rra", rc));
    546718
    547719    int ch;
     
    684856                       const ComPtr<ICloudClient> &pClient)
    685857{
     858    MachineSpec machineSpec;
     859    ComPtr<ICloudMachine> pMachine;
    686860    HRESULT hrc;
     861    int rc;
     862
     863    enum
     864    {
     865        kMachineInfoIota = 1000,
     866        kMachineInfo_Details,
     867    };
    687868
    688869    // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_INFO);
    689 
    690     if (iFirst == a->argc)
    691     {
    692         return RTMsgErrorExit(RTEXITCODE_SYNTAX,
    693                    "cloud machine info: machine id required\n"
    694                    "Try '--help' for more information.");
    695     }
    696 
    697     for (int i = iFirst; i < a->argc; ++i)
    698     {
    699         ComPtr<ICloudMachine> pMachine;
    700         hrc = getMachine(pMachine, pClient, a->argv[i]);
    701         if (hrc == VBOX_E_OBJECT_NOT_FOUND)
    702             return RTMsgErrorExit(RTEXITCODE_FAILURE,
    703                        "%s: not found", a->argv[i]);
    704         else if (FAILED(hrc))
    705             return RTEXITCODE_FAILURE;
    706 
    707         hrc = printMachineInfo(pMachine);
    708         if (FAILED(hrc))
    709             return RTEXITCODE_FAILURE;
    710     }
     870    static const RTGETOPTDEF s_aOptions[] =
     871    {
     872        { "--details", kMachineInfo_Details, RTGETOPT_REQ_NOTHING },
     873        CLOUD_MACHINE_RTGETOPTDEF_MACHINE,
     874        CLOUD_MACHINE_RTGETOPTDEF_HELP
     875    };
     876
     877    RTGETOPTSTATE OptState;
     878    rc = RTGetOptInit(&OptState, a->argc, a->argv,
     879                      s_aOptions, RT_ELEMENTS(s_aOptions),
     880                      iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
     881    AssertRCReturn(rc, RTMsgErrorExit(RTEXITCODE_INIT,
     882                           "RTGetOptInit: %Rra", rc));
     883
     884    int ch;
     885    RTGETOPTUNION Val;
     886    while ((ch = RTGetOpt(&OptState, &Val)) != 0)
     887    {
     888        rc = checkMachineSpecArgument(machineSpec, ch, Val);
     889        if (rc == VINF_SUCCESS)
     890            continue;
     891        else if (rc == VINF_CALLBACK_RETURN)
     892            return RTEXITCODE_SUCCESS;
     893        else if (rc == VERR_PARSE_ERROR)
     894            return RTEXITCODE_SYNTAX;
     895
     896        switch (ch)
     897        {
     898            case kMachineInfo_Details:
     899                /* currently no-op */
     900                break;
     901
     902            default:
     903                return RTGetOptPrintError(ch, &Val);
     904        }
     905    }
     906
     907    hrc = getMachineBySpec(pMachine, pClient, machineSpec);
     908    if (FAILED(hrc))
     909        return RTEXITCODE_FAILURE;
     910
     911
     912    hrc = printMachineInfo(pMachine);
     913    if (FAILED(hrc))
     914        return RTEXITCODE_FAILURE;
    711915
    712916    return RTEXITCODE_SUCCESS;
     
    9501154                                 const ComPtr<ICloudClient> &pClient)
    9511155{
     1156    MachineSpec machineSpec;
     1157    ComPtr<ICloudMachine> pMachine;
    9521158    HRESULT hrc;
     1159    int rc;
    9531160
    9541161    // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_CONSOLEHISTORY);
    955 
    956     if (iFirst == a->argc)
    957     {
    958         return RTMsgErrorExit(RTEXITCODE_SYNTAX,
    959                    "cloud machine info: machine id required\n"
    960                    "Try '--help' for more information.");
    961     }
    962 
    963     if (a->argc - iFirst > 1)
    964     {
    965         return RTMsgErrorExit(RTEXITCODE_SYNTAX,
    966                    "cloud machine info: too many arguments\n"
    967                    "Try '--help' for more information.");
    968     }
    969 
    970     ComPtr<ICloudMachine> pMachine;
    971     hrc = getMachine(pMachine, pClient, a->argv[iFirst]);
     1162    static const RTGETOPTDEF s_aOptions[] =
     1163    {
     1164        CLOUD_MACHINE_RTGETOPTDEF_MACHINE,
     1165        CLOUD_MACHINE_RTGETOPTDEF_HELP
     1166    };
     1167
     1168    RTGETOPTSTATE OptState;
     1169    rc = RTGetOptInit(&OptState, a->argc, a->argv,
     1170                      s_aOptions, RT_ELEMENTS(s_aOptions),
     1171                      iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
     1172    AssertRCStmt(rc,
     1173        return RTMsgErrorExit(RTEXITCODE_INIT, /* internal error */
     1174                   "RTGetOptInit: %Rra", rc));
     1175
     1176    int ch;
     1177    RTGETOPTUNION Val;
     1178    while ((ch = RTGetOpt(&OptState, &Val)) != 0)
     1179    {
     1180        rc = checkMachineSpecArgument(machineSpec, ch, Val);
     1181        if (rc == VINF_SUCCESS)
     1182            continue;
     1183        else if (rc == VINF_CALLBACK_RETURN)
     1184            return RTEXITCODE_SUCCESS;
     1185        else if (rc == VERR_PARSE_ERROR)
     1186            return RTEXITCODE_SYNTAX;
     1187
     1188        switch (ch)
     1189        {
     1190            /* no other options currently */
     1191            default:
     1192                return RTGetOptPrintError(ch, &Val);
     1193        }
     1194    }
     1195
     1196    hrc = getMachineBySpec(pMachine, pClient, machineSpec);
    9721197    if (FAILED(hrc))
    9731198        return RTEXITCODE_FAILURE;
     1199
    9741200
    9751201    ComPtr<IDataStream> pHistoryStream;
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