Changeset 90268 in vbox for trunk/src/VBox
- Timestamp:
- Jul 21, 2021 1:51:37 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageCloudMachine.cpp
r90235 r90268 24 24 #include <VBox/com/errorprint.h> 25 25 26 #include <algorithm> 27 #include <vector> 28 26 29 27 30 static int selectCloudProvider(ComPtr<ICloudProvider> &pProvider, … … 36 39 static RTEXITCODE listCloudMachinesImpl(HandlerArg *a, int iFirst, 37 40 const ComPtr<ICloudProfile> &pProfile); 41 static RTEXITCODE handleCloudMachineInfo(HandlerArg *a, int iFirst, 42 const ComPtr<ICloudProfile> &pProfile); 43 44 static HRESULT printMachineInfo(const ComPtr<ICloudMachine> &pMachine); 45 static HRESULT printFormValue(const ComPtr<IFormValue> &pValue); 38 46 39 47 … … 208 216 209 217 218 static HRESULT 219 getMachineById(ComPtr<ICloudMachine> &pMachineOut, 220 const ComPtr<ICloudProfile> &pProfile, 221 const char *pcszStrId) 222 { 223 HRESULT hrc; 224 225 ComPtr<ICloudClient> pCloudClient; 226 CHECK_ERROR2_RET(hrc, pProfile, 227 CreateCloudClient(pCloudClient.asOutParam()), hrc); 228 229 ComPtr<ICloudMachine> pMachine; 230 CHECK_ERROR2_RET(hrc, pCloudClient, 231 GetCloudMachine(com::Bstr(pcszStrId).raw(), 232 pMachine.asOutParam()), hrc); 233 234 ComPtr<IProgress> pRefreshProgress; 235 CHECK_ERROR2_RET(hrc, pMachine, 236 Refresh(pRefreshProgress.asOutParam()), hrc); 237 238 hrc = showProgress(pRefreshProgress, SHOW_PROGRESS_NONE); 239 if (FAILED(hrc)) 240 return hrc; 241 242 pMachineOut = pMachine; 243 return S_OK; 244 } 245 246 210 247 /* 211 248 * RTGETOPTINIT_FLAGS_NO_STD_OPTS recognizes both --help and --version … … 266 303 { 267 304 case kMachine_Info: 268 return RTMsgErrorExit(RTEXITCODE_FAILURE, 269 "cloud machine info: not yet implemented"); 305 return handleCloudMachineInfo(a, OptState.iNext, pProfile); 270 306 271 307 case kMachine_List: … … 335 371 { 336 372 { "--long", 'l', RTGETOPT_REQ_NOTHING }, 337 { "--s hort",'s', RTGETOPT_REQ_NOTHING },373 { "--sort", 's', RTGETOPT_REQ_NOTHING }, 338 374 CLOUD_MACHINE_RTGETOPTDEF_HELP 339 375 }; 340 376 341 enum kFormatEnum 342 { 343 kFormat_Default, 344 kFormat_Short, 345 kFormat_Long 346 }; 377 enum kFormatEnum { kFormat_Short, kFormat_Long }; 378 kFormatEnum enmFormat = kFormat_Short; 379 380 enum kSortOrderEnum { kSortOrder_None, kSortOrder_Name, kSortOrder_Id }; 381 kSortOrderEnum enmSortOrder = kSortOrder_None; 347 382 348 383 HRESULT hrc; 349 384 int rc; 350 351 kFormatEnum enmFormat = kFormat_Default;352 385 353 386 … … 371 404 372 405 case 's': 373 enmFormat = kFormat_Short; 406 /** @todo optional argument to select the sort key? */ 407 enmSortOrder = kSortOrder_Name; 374 408 break; 375 409 … … 407 441 RTEXITCODE_FAILURE); 408 442 409 for (size_t i = 0; i < aMachines.size(); ++i) 410 { 411 const ComPtr<ICloudMachine> pMachine = aMachines[i]; 412 413 com::Bstr bstrId; 443 const size_t cMachines = aMachines.size(); 444 if (cMachines == 0) 445 return RTEXITCODE_SUCCESS; 446 447 448 /* 449 * Get names/ids that we need for the short output and to sort the 450 * list. 451 */ 452 std::vector<ComPtr<ICloudMachine> > vMachines(cMachines); 453 std::vector<com::Bstr> vBstrNames(cMachines); 454 std::vector<com::Bstr> vBstrIds(cMachines); 455 for (size_t i = 0; i < cMachines; ++i) 456 { 457 vMachines[i] = aMachines[i]; 458 459 CHECK_ERROR2_RET(hrc, vMachines[i], 460 COMGETTER(Name)(vBstrNames[i].asOutParam()), 461 RTEXITCODE_FAILURE); 462 463 CHECK_ERROR2_RET(hrc, vMachines[i], 464 COMGETTER(Id)(vBstrIds[i].asOutParam()), 465 RTEXITCODE_FAILURE); 466 } 467 468 469 /* 470 * Sort the list if necessary. The sort is indirect via an 471 * intermediate array of indexes. 472 */ 473 std::vector<size_t> vIndexes(cMachines); 474 for (size_t i = 0; i < cMachines; ++i) 475 vIndexes[i] = i; 476 477 if (enmSortOrder != kSortOrder_None) 478 { 479 struct SortBy { 480 const std::vector<com::Bstr> &ks; 481 SortBy(const std::vector<com::Bstr> &aKeys) : ks(aKeys) {} 482 bool operator() (size_t l, size_t r) { return ks[l] < ks[r]; } 483 }; 484 485 std::sort(vIndexes.begin(), vIndexes.end(), 486 SortBy(enmSortOrder == kSortOrder_Name 487 ? vBstrNames : vBstrIds)); 488 } 489 490 491 if (enmFormat == kFormat_Short) 492 { 493 for (size_t i = 0; i < cMachines; ++i) 494 { 495 const size_t idx = vIndexes[i]; 496 const com::Bstr &bstrId = vBstrIds[idx]; 497 const com::Bstr &bstrName = vBstrNames[idx]; 498 499 RTPrintf("%ls %ls\n", bstrId.raw(), bstrName.raw()); 500 } 501 } 502 else // kFormat_Long 503 { 504 for (size_t i = 0; i < cMachines; ++i) 505 { 506 const size_t idx = vIndexes[i]; 507 const ComPtr<ICloudMachine> &pMachine = vMachines[idx]; 508 509 if (i != 0) 510 RTPrintf("\n"); 511 printMachineInfo(pMachine); 512 } 513 } 514 515 return RTEXITCODE_SUCCESS; 516 } 517 518 519 static RTEXITCODE 520 handleCloudMachineInfo(HandlerArg *a, int iFirst, 521 const ComPtr<ICloudProfile> &pProfile) 522 { 523 HRESULT hrc; 524 525 if (a->argc == iFirst) 526 { 527 return RTMsgErrorExit(RTEXITCODE_SYNTAX, 528 "cloud machine info: machine id required\n" 529 "Try '--help' for more information."); 530 } 531 532 for (int i = iFirst; i < a->argc; ++i) 533 { 534 ComPtr<ICloudMachine> pMachine; 535 hrc = getMachineById(pMachine, pProfile, a->argv[i]); 536 if (FAILED(hrc)) 537 return RTEXITCODE_FAILURE; 538 539 hrc = printMachineInfo(pMachine); 540 if (FAILED(hrc)) 541 return RTEXITCODE_FAILURE; 542 } 543 544 return RTEXITCODE_SUCCESS; 545 } 546 547 548 static HRESULT 549 printMachineInfo(const ComPtr<ICloudMachine> &pMachine) 550 { 551 HRESULT hrc; 552 553 /* 554 * Check if the machine is accessible and print the error 555 * message if not. 556 */ 557 BOOL fAccessible = FALSE; 558 CHECK_ERROR2_RET(hrc, pMachine, 559 COMGETTER(Accessible)(&fAccessible), hrc); 560 561 if (!fAccessible) 562 { 563 RTMsgError("machine is not accessible"); // XXX: Id? 564 565 ComPtr<IVirtualBoxErrorInfo> pErrorInfo; 414 566 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 } 567 COMGETTER(AccessError)(pErrorInfo.asOutParam()), hrc); 568 569 while (!pErrorInfo.isNull()) 570 { 571 com::Bstr bstrText; 572 CHECK_ERROR2_RET(hrc, pErrorInfo, 573 COMGETTER(Text)(bstrText.asOutParam()), hrc); 574 RTStrmPrintf(g_pStdErr, "%ls\n", bstrText.raw()); 575 576 CHECK_ERROR2_RET(hrc, pErrorInfo, 577 COMGETTER(Next)(pErrorInfo.asOutParam()), hrc); 578 } 579 580 return E_FAIL; 581 } 582 583 584 /* 585 * The machine seems to be ok, print its details. 586 */ 587 ComPtr<IForm> pDetails; 588 CHECK_ERROR2_RET(hrc, pMachine, 589 GetDetailsForm(pDetails.asOutParam()), hrc); 590 591 if (RT_UNLIKELY(pDetails.isNull())) 592 { 593 RTMsgError("null details"); /* better error message? */ 594 return E_FAIL; 595 } 596 597 com::SafeIfaceArray<IFormValue> aValues; 598 CHECK_ERROR2_RET(hrc, pDetails, 599 COMGETTER(Values)(ComSafeArrayAsOutParam(aValues)), hrc); 600 for (size_t i = 0; i < aValues.size(); ++i) 601 { 602 hrc = printFormValue(aValues[i]); 603 if (FAILED(hrc)) 604 return hrc; 605 } 606 607 return S_OK; 608 } 609 610 611 static HRESULT 612 printFormValue(const ComPtr<IFormValue> &pValue) 613 { 614 HRESULT hrc; 615 616 BOOL fVisible = FALSE; 617 CHECK_ERROR2_RET(hrc, pValue, 618 COMGETTER(Visible)(&fVisible), hrc); 619 if (!fVisible) 620 return S_OK; 621 622 623 com::Bstr bstrLabel; 624 CHECK_ERROR2_RET(hrc, pValue, 625 COMGETTER(Label)(bstrLabel.asOutParam()), hrc); 626 627 FormValueType_T enmType; 628 CHECK_ERROR2_RET(hrc, pValue, 629 COMGETTER(Type)(&enmType), hrc); 630 631 switch (enmType) 632 { 633 case FormValueType_Boolean: 634 { 635 ComPtr<IBooleanFormValue> pBoolValue; 636 hrc = pValue.queryInterfaceTo(pBoolValue.asOutParam()); 637 if (FAILED(hrc)) 638 { 639 RTStrmPrintf(g_pStdErr, 640 "%ls: unable to obtain boolean value\n", bstrLabel.raw()); 641 break; 642 } 643 644 BOOL fSelected; 645 hrc = pBoolValue->GetSelected(&fSelected); 646 if (FAILED(hrc)) 647 { 648 RTStrmPrintf(g_pStdOut, 649 "%ls: %Rhra", bstrLabel.raw(), hrc); 650 break; 651 } 652 653 RTPrintf("%ls: %RTbool\n", 654 bstrLabel.raw(), RT_BOOL(fSelected)); 655 break; 656 } 657 658 case FormValueType_String: 659 { 660 ComPtr<IStringFormValue> pStrValue; 661 hrc = pValue.queryInterfaceTo(pStrValue.asOutParam()); 662 if (FAILED(hrc)) 663 { 664 RTStrmPrintf(g_pStdErr, 665 "%ls: unable to obtain string value\n", bstrLabel.raw()); 666 break; 667 } 668 669 /* 670 * GUI hack: if clipboard string is set, it contains 671 * untruncated long value, usually full OCID, so check it 672 * first. Make this selectable with an option? 673 */ 674 com::Bstr bstrValue; 675 hrc = pStrValue->GetClipboardString(bstrValue.asOutParam()); 676 if (FAILED(hrc)) 677 { 678 RTStrmPrintf(g_pStdOut, 679 "%ls: %Rhra", bstrLabel.raw(), hrc); 680 break; 681 } 682 683 if (bstrValue.isEmpty()) 684 { 685 hrc = pStrValue->GetString(bstrValue.asOutParam()); 686 if (FAILED(hrc)) 687 { 688 RTStrmPrintf(g_pStdOut, 689 "%ls: %Rhra", bstrLabel.raw(), hrc); 690 break; 691 } 692 } 693 694 RTPrintf("%ls: %ls\n", 695 bstrLabel.raw(), bstrValue.raw()); 696 break; 697 } 698 699 case FormValueType_RangedInteger: 700 RTStrmPrintf(g_pStdOut, "integer\n"); 701 break; 702 703 case FormValueType_Choice: 704 RTStrmPrintf(g_pStdOut, "choice\n"); 705 break; 706 707 default: 708 RTStrmPrintf(g_pStdOut, "unknown value type %RU32\n", enmType); 709 break; 710 } 711 712 return S_OK; 713 }
Note:
See TracChangeset
for help on using the changeset viewer.