VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageCloud.cpp

Last change on this file was 102637, checked in by vboxsync, 5 months ago

Removed excessive code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 115.2 KB
RevLine 
[77883]1/* $Id: VBoxManageCloud.cpp 102637 2023-12-18 15:56:11Z vboxsync $ */
2/** @file
3 * VBoxManageCloud - The cloud related commands.
4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[77883]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[77883]26 */
27
28#include <VBox/com/com.h>
29#include <VBox/com/string.h>
30#include <VBox/com/Guid.h>
31#include <VBox/com/array.h>
32#include <VBox/com/ErrorInfo.h>
33#include <VBox/com/errorprint.h>
34#include <VBox/com/VirtualBox.h>
35
36#include <iprt/ctype.h>
37#include <iprt/getopt.h>
38#include <iprt/stream.h>
39#include <iprt/string.h>
[84640]40#include <iprt/thread.h>
[77883]41#include <iprt/uuid.h>
42#include <iprt/file.h>
[85139]43#include <iprt/http.h>
[77883]44#include <VBox/log.h>
45
[84639]46#include <iprt/cpp/path.h>
47
[77883]48#include "VBoxManage.h"
49
50#include <list>
[102095]51#include <vector>
[77883]52
53using namespace com;//at least for Bstr
54
[92372]55DECLARE_TRANSLATION_CONTEXT(Cloud);
[102095]56DECLARE_TRANSLATION_CONTEXT(CloudMachine);
[90214]57
[77883]58/**
59 * Common Cloud options.
60 */
61typedef struct
62{
[78734]63 struct {
64 const char *pszProviderName;
65 ComPtr<ICloudProvider> pCloudProvider;
66 }provider;
67 struct {
68 const char *pszProfileName;
69 ComPtr<ICloudProfile> pCloudProfile;
70 }profile;
71
[77883]72} CLOUDCOMMONOPT;
73typedef CLOUDCOMMONOPT *PCLOUDCOMMONOPT;
74
[78734]75static HRESULT checkAndSetCommonOptions(HandlerArg *a, PCLOUDCOMMONOPT pCommonOpts)
76{
77 HRESULT hrc = S_OK;
78
79 Bstr bstrProvider(pCommonOpts->provider.pszProviderName);
80 Bstr bstrProfile(pCommonOpts->profile.pszProfileName);
81
82 /* check for required options */
83 if (bstrProvider.isEmpty())
84 {
[94238]85 errorSyntax(Cloud::tr("Parameter --provider is required"));
[78734]86 return E_FAIL;
87 }
88 if (bstrProfile.isEmpty())
89 {
[94238]90 errorSyntax(Cloud::tr("Parameter --profile is required"));
[78734]91 return E_FAIL;
92 }
93
94 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
95 ComPtr<ICloudProviderManager> pCloudProviderManager;
96 CHECK_ERROR2_RET(hrc, pVirtualBox,
97 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
98 RTEXITCODE_FAILURE);
99
100 ComPtr<ICloudProvider> pCloudProvider;
101 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
102 GetProviderByShortName(bstrProvider.raw(), pCloudProvider.asOutParam()),
103 RTEXITCODE_FAILURE);
104 pCommonOpts->provider.pCloudProvider = pCloudProvider;
105
106 ComPtr<ICloudProfile> pCloudProfile;
107 CHECK_ERROR2_RET(hrc, pCloudProvider,
108 GetProfileByName(bstrProfile.raw(), pCloudProfile.asOutParam()),
109 RTEXITCODE_FAILURE);
110 pCommonOpts->profile.pCloudProfile = pCloudProfile;
111
112 return hrc;
113}
114
[79869]115
[77883]116/**
[77885]117 * List all available cloud instances for the specified cloud provider.
118 * Available cloud instance is one which state whether "running" or "stopped".
119 *
[77883]120 * @returns RTEXITCODE
[77885]121 * @param a is the list of passed arguments
122 * @param iFirst is the position of the first unparsed argument in the arguments list
123 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
[77883]124 * arguments which have been already parsed before
125 */
126static RTEXITCODE listCloudInstances(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
127{
128 static const RTGETOPTDEF s_aOptions[] =
129 {
[79039]130 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
[83279]131 { "--state", 's', RTGETOPT_REQ_STRING },
[93872]132 { "help", 'h', RTGETOPT_REQ_NOTHING },
133 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[77883]134 };
135 RTGETOPTSTATE GetState;
136 RTGETOPTUNION ValueUnion;
137 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
138 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
139
140 Utf8Str strCompartmentId;
[79869]141 com::SafeArray<CloudMachineState_T> machineStates;
[79039]142
[77883]143 int c;
144 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
145 {
146 switch (c)
147 {
148 case 'c':
[79039]149 strCompartmentId = ValueUnion.psz;
[77883]150 break;
[79869]151
[79039]152 case 's':
[79869]153 {
154 const char * const pszState = ValueUnion.psz;
155
156 if (RTStrICmp(pszState, "creatingimage") == 0)
157 machineStates.push_back(CloudMachineState_CreatingImage);
158 else if (RTStrICmp(pszState, "paused") == 0) /* XXX */
159 machineStates.push_back(CloudMachineState_Stopped);
160 else if (RTStrICmp(pszState, "provisioning") == 0)
161 machineStates.push_back(CloudMachineState_Provisioning);
162 else if (RTStrICmp(pszState, "running") == 0)
163 machineStates.push_back(CloudMachineState_Running);
164 else if (RTStrICmp(pszState, "starting") == 0)
165 machineStates.push_back(CloudMachineState_Starting);
166 else if (RTStrICmp(pszState, "stopped") == 0)
167 machineStates.push_back(CloudMachineState_Stopped);
168 else if (RTStrICmp(pszState, "stopping") == 0)
169 machineStates.push_back(CloudMachineState_Stopping);
170 else if (RTStrICmp(pszState, "terminated") == 0)
171 machineStates.push_back(CloudMachineState_Terminated);
172 else if (RTStrICmp(pszState, "terminating") == 0)
173 machineStates.push_back(CloudMachineState_Terminating);
174 else
[92372]175 return errorArgument(Cloud::tr("Unknown cloud instance state \"%s\""), pszState);
[79039]176 break;
[79869]177 }
[93872]178 case 'h':
[83279]179 printHelp(g_pStdOut);
180 return RTEXITCODE_SUCCESS;
[77883]181 case VINF_GETOPT_NOT_OPTION:
182 return errorUnknownSubcommand(ValueUnion.psz);
[79869]183
[77883]184 default:
185 return errorGetOpt(c, &ValueUnion);
186 }
187 }
188
189 HRESULT hrc = S_OK;
[83279]190
191 /* Delayed check. It allows us to print help information.*/
192 hrc = checkAndSetCommonOptions(a, pCommonOpts);
193 if (FAILED(hrc))
194 return RTEXITCODE_FAILURE;
195
[77883]196 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
[79869]197
[77883]198 ComPtr<ICloudProviderManager> pCloudProviderManager;
199 CHECK_ERROR2_RET(hrc, pVirtualBox,
200 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
201 RTEXITCODE_FAILURE);
[79869]202
[77883]203 ComPtr<ICloudProvider> pCloudProvider;
204 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
[78734]205 GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()),
[77883]206 RTEXITCODE_FAILURE);
[79869]207
[77883]208 ComPtr<ICloudProfile> pCloudProfile;
209 CHECK_ERROR2_RET(hrc, pCloudProvider,
[78734]210 GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()),
[77883]211 RTEXITCODE_FAILURE);
212
213 if (strCompartmentId.isNotEmpty())
214 {
215 CHECK_ERROR2_RET(hrc, pCloudProfile,
216 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),
217 RTEXITCODE_FAILURE);
218 }
219 else
220 {
[92372]221 RTPrintf(Cloud::tr("Parameter \'compartment\' is empty or absent.\n"
222 "Trying to get the compartment from the passed cloud profile \'%s\'\n"),
223 pCommonOpts->profile.pszProfileName);
[77883]224 Bstr bStrCompartmentId;
225 CHECK_ERROR2_RET(hrc, pCloudProfile,
226 GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()),
227 RTEXITCODE_FAILURE);
228 strCompartmentId = bStrCompartmentId;
[78734]229 if (strCompartmentId.isNotEmpty())
[92372]230 RTPrintf(Cloud::tr("Found the compartment \'%s\':\n"), strCompartmentId.c_str());
[78734]231 else
[94238]232 return errorSyntax(Cloud::tr("Parameter --compartment-id is required"));
[77883]233 }
234
235 Bstr bstrProfileName;
236 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
237
238 ComObjPtr<ICloudClient> oCloudClient;
239 CHECK_ERROR2_RET(hrc, pCloudProfile,
240 CreateCloudClient(oCloudClient.asOutParam()),
241 RTEXITCODE_FAILURE);
242
[78148]243 ComPtr<IStringArray> pVMNamesHolder;
244 ComPtr<IStringArray> pVMIdsHolder;
[77883]245 com::SafeArray<BSTR> arrayVMNames;
246 com::SafeArray<BSTR> arrayVMIds;
[78148]247 ComPtr<IProgress> pProgress;
248
[92372]249 RTPrintf(Cloud::tr("Reply is in the form \'instance name\' = \'instance id\'\n"));
[79033]250
[77883]251 CHECK_ERROR2_RET(hrc, oCloudClient,
[79727]252 ListInstances(ComSafeArrayAsInParam(machineStates),
[78148]253 pVMNamesHolder.asOutParam(),
254 pVMIdsHolder.asOutParam(),
255 pProgress.asOutParam()),
[77883]256 RTEXITCODE_FAILURE);
[78148]257 showProgress(pProgress);
[92372]258 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Failed to list instances")), RTEXITCODE_FAILURE);
[78148]259
260 CHECK_ERROR2_RET(hrc,
261 pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)),
262 RTEXITCODE_FAILURE);
263 CHECK_ERROR2_RET(hrc,
264 pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)),
265 RTEXITCODE_FAILURE);
266
[92594]267 RTPrintf(Cloud::tr("The list of the instances for the cloud profile \'%ls\'\nand compartment \'%s\':\n"),
[77883]268 bstrProfileName.raw(), strCompartmentId.c_str());
269 size_t cIds = arrayVMIds.size();
270 size_t cNames = arrayVMNames.size();
271 for (size_t k = 0; k < cNames; k++)
272 {
273 Bstr value;
274 if (k < cIds)
275 value = arrayVMIds[k];
276 RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw());
277 }
[78148]278
[77883]279 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
280}
281
[79869]282
[77883]283/**
284 * List all available cloud images for the specified cloud provider.
285 *
286 * @returns RTEXITCODE
[77885]287 * @param a is the list of passed arguments
288 * @param iFirst is the position of the first unparsed argument in the arguments list
289 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
[77883]290 * arguments which have been already parsed before
291 */
292static RTEXITCODE listCloudImages(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
293{
294 static const RTGETOPTDEF s_aOptions[] =
295 {
[79062]296 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
[83279]297 { "--state", 's', RTGETOPT_REQ_STRING },
[93872]298 { "help", 'h', RTGETOPT_REQ_NOTHING },
299 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[77883]300 };
301 RTGETOPTSTATE GetState;
302 RTGETOPTUNION ValueUnion;
303 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
304 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
305
[79869]306 Utf8Str strCompartmentId;
[79797]307 com::SafeArray<CloudImageState_T> imageStates;
308
[77883]309 int c;
310 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
311 {
312 switch (c)
313 {
314 case 'c':
[79062]315 strCompartmentId = ValueUnion.psz;
[77883]316 break;
[79797]317
[79062]318 case 's':
[79797]319 {
320 const char * const pszState = ValueUnion.psz;
321
322 if (RTStrICmp(pszState, "available") == 0)
323 imageStates.push_back(CloudImageState_Available);
324 else if (RTStrICmp(pszState, "deleted") == 0)
325 imageStates.push_back(CloudImageState_Deleted);
326 else if (RTStrICmp(pszState, "disabled") == 0)
327 imageStates.push_back(CloudImageState_Disabled);
328 else if (RTStrICmp(pszState, "exporting") == 0)
329 imageStates.push_back(CloudImageState_Exporting);
330 else if (RTStrICmp(pszState, "importing") == 0)
331 imageStates.push_back(CloudImageState_Importing);
332 else if (RTStrICmp(pszState, "provisioning") == 0)
333 imageStates.push_back(CloudImageState_Provisioning);
334 else
[92372]335 return errorArgument(Cloud::tr("Unknown cloud image state \"%s\""), pszState);
[79062]336 break;
[79797]337 }
[93872]338 case 'h':
[83279]339 printHelp(g_pStdOut);
340 return RTEXITCODE_SUCCESS;
[77883]341 case VINF_GETOPT_NOT_OPTION:
342 return errorUnknownSubcommand(ValueUnion.psz);
[79797]343
[77883]344 default:
345 return errorGetOpt(c, &ValueUnion);
346 }
347 }
348
[79062]349
[77883]350 HRESULT hrc = S_OK;
[83279]351
352 /* Delayed check. It allows us to print help information.*/
353 hrc = checkAndSetCommonOptions(a, pCommonOpts);
354 if (FAILED(hrc))
355 return RTEXITCODE_FAILURE;
356
[77883]357 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
[79797]358
[77883]359 ComPtr<ICloudProviderManager> pCloudProviderManager;
360 CHECK_ERROR2_RET(hrc, pVirtualBox,
361 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
362 RTEXITCODE_FAILURE);
[79797]363
[77883]364 ComPtr<ICloudProvider> pCloudProvider;
365 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
[78734]366 GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()),
[77883]367 RTEXITCODE_FAILURE);
[79797]368
[77883]369 ComPtr<ICloudProfile> pCloudProfile;
370 CHECK_ERROR2_RET(hrc, pCloudProvider,
[78734]371 GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()),
[77883]372 RTEXITCODE_FAILURE);
[79797]373
[77883]374 if (strCompartmentId.isNotEmpty())
375 {
376 CHECK_ERROR2_RET(hrc, pCloudProfile,
[99931]377 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),
[77883]378 RTEXITCODE_FAILURE);
379 }
380 else
381 {
[92372]382 RTPrintf(Cloud::tr("Parameter \'compartment\' is empty or absent.\n"
383 "Trying to get the compartment from the passed cloud profile \'%s\'\n"),
384 pCommonOpts->profile.pszProfileName);
[77883]385 Bstr bStrCompartmentId;
386 CHECK_ERROR2_RET(hrc, pCloudProfile,
387 GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()),
388 RTEXITCODE_FAILURE);
389 strCompartmentId = bStrCompartmentId;
[78734]390 if (strCompartmentId.isNotEmpty())
[92372]391 RTPrintf(Cloud::tr("Found the compartment \'%s\':\n"), strCompartmentId.c_str());
[78734]392 else
[94238]393 return errorSyntax(Cloud::tr("Parameter --compartment-id is required"));
[77883]394 }
395
396 Bstr bstrProfileName;
397 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
398
399 ComObjPtr<ICloudClient> oCloudClient;
400 CHECK_ERROR2_RET(hrc, pCloudProfile,
401 CreateCloudClient(oCloudClient.asOutParam()),
[77885]402 RTEXITCODE_FAILURE);
[78148]403
404 ComPtr<IStringArray> pVMNamesHolder;
405 ComPtr<IStringArray> pVMIdsHolder;
[77883]406 com::SafeArray<BSTR> arrayVMNames;
407 com::SafeArray<BSTR> arrayVMIds;
[78148]408 ComPtr<IProgress> pProgress;
409
[92372]410 RTPrintf(Cloud::tr("Reply is in the form \'image name\' = \'image id\'\n"));
[77883]411 CHECK_ERROR2_RET(hrc, oCloudClient,
[79062]412 ListImages(ComSafeArrayAsInParam(imageStates),
[78148]413 pVMNamesHolder.asOutParam(),
414 pVMIdsHolder.asOutParam(),
415 pProgress.asOutParam()),
[77883]416 RTEXITCODE_FAILURE);
[78148]417 showProgress(pProgress);
[92372]418 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Failed to list images")), RTEXITCODE_FAILURE);
[78148]419
420 CHECK_ERROR2_RET(hrc,
421 pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)),
422 RTEXITCODE_FAILURE);
423 CHECK_ERROR2_RET(hrc,
424 pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)),
425 RTEXITCODE_FAILURE);
426
[92594]427 RTPrintf(Cloud::tr("The list of the images for the cloud profile \'%ls\'\nand compartment \'%s\':\n"),
[77883]428 bstrProfileName.raw(), strCompartmentId.c_str());
429 size_t cNames = arrayVMNames.size();
430 size_t cIds = arrayVMIds.size();
431 for (size_t k = 0; k < cNames; k++)
432 {
433 Bstr value;
434 if (k < cIds)
435 value = arrayVMIds[k];
436 RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw());
437 }
438
439 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
440}
441
[98701]442
[77883]443/**
[98852]444 * List all available cloud vnic attachments for the specified cloud provider.
445 *
446 * @returns RTEXITCODE
447 * @param a is the list of passed arguments
448 * @param iFirst is the position of the first unparsed argument in the arguments list
449 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
450 * arguments which have been already parsed before
451 */
452static RTEXITCODE listCloudVnicAttachments(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
453{
454 static const RTGETOPTDEF s_aOptions[] =
455 {
456 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
457 { "--filter", 'f', RTGETOPT_REQ_STRING },/*instanceId=<id>, vnicId=<id>, domainName=<name>*/
458 { "help", 'h', RTGETOPT_REQ_NOTHING },
459 { "--help", 'h', RTGETOPT_REQ_NOTHING }
460 };
461 RTGETOPTSTATE GetState;
462 RTGETOPTUNION ValueUnion;
463 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
464 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
465
466 com::SafeArray<BSTR> parameters;
467 Utf8Str strCompartmentId;
468 Utf8Str filterList;
469 HRESULT hrc = S_OK;
470
471 int c;
472 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
473 {
474 switch (c)
475 {
476 case 'c':
477 strCompartmentId = ValueUnion.psz;
478 Bstr(Utf8Str("compartmentId=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
479 break;
480
481 case 'f':
482 filterList.append(ValueUnion.psz).append(",");
483 Bstr(Utf8Str(ValueUnion.psz)).detachTo(parameters.appendedRaw());
484 break;
485 case 'h':
486 printHelp(g_pStdOut);
487 return RTEXITCODE_SUCCESS;
488 case VINF_GETOPT_NOT_OPTION:
489 return errorUnknownSubcommand(ValueUnion.psz);
490
491 default:
492 return errorGetOpt(c, &ValueUnion);
493 }
494 }
495
496 RTPrintf(Cloud::tr("Filters: \'%s\' \n"), filterList.c_str());
497
498 /* Delayed check. It allows us to print help information.*/
499 hrc = checkAndSetCommonOptions(a, pCommonOpts);
500 if (FAILED(hrc))
501 return RTEXITCODE_FAILURE;
502
503 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
504
505 ComPtr<ICloudProviderManager> pCloudProviderManager;
506 CHECK_ERROR2_RET(hrc, pVirtualBox,
507 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
508 RTEXITCODE_FAILURE);
509
510 ComPtr<ICloudProvider> pCloudProvider;
511 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
512 GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()),
513 RTEXITCODE_FAILURE);
514
515 ComPtr<ICloudProfile> pCloudProfile;
516 CHECK_ERROR2_RET(hrc, pCloudProvider,
517 GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()),
518 RTEXITCODE_FAILURE);
519
520 if (strCompartmentId.isNotEmpty())
521 {
522 CHECK_ERROR2_RET(hrc, pCloudProfile,
[99931]523 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),
[98852]524 RTEXITCODE_FAILURE);
525 }
526 else
527 {
528 RTPrintf(Cloud::tr("Parameter \'compartment\' is empty or absent.\n"
529 "Trying to get the compartment from the passed cloud profile \'%s\'\n"), pCommonOpts->profile.pszProfileName);
530 Bstr bStrCompartmentId;
531 CHECK_ERROR2_RET(hrc, pCloudProfile,
532 GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()),
533 RTEXITCODE_FAILURE);
534 strCompartmentId = bStrCompartmentId;
535 if (strCompartmentId.isNotEmpty())
536 RTPrintf(Cloud::tr("Found the compartment \'%s\':\n"), strCompartmentId.c_str());
537 else
538 return errorArgument(Cloud::tr("Parameter --compartment-id is required."));
539 }
540
541 Bstr bstrProfileName;
542 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
543
544 ComObjPtr<ICloudClient> oCloudClient;
545 CHECK_ERROR2_RET(hrc, pCloudProfile,
546 CreateCloudClient(oCloudClient.asOutParam()),
547 RTEXITCODE_FAILURE);
548
549 ComPtr<IStringArray> pVnicAttachmentIdsHolder;
550 ComPtr<IStringArray> pVnicIdsHolder;
551 com::SafeArray<BSTR> arrayVnicAttachmentIds;
552 com::SafeArray<BSTR> arrayVnicIds;
553 ComPtr<IProgress> pProgress;
554
555 RTPrintf(Cloud::tr("Reply is in the form \'Vnic attachment <id>\': \n\t \'Vnic <id>\'\n"));
556 CHECK_ERROR2_RET(hrc, oCloudClient,
557 ListVnicAttachments(ComSafeArrayAsInParam(parameters),
558 pVnicAttachmentIdsHolder.asOutParam(),
559 pVnicIdsHolder.asOutParam(),
560 pProgress.asOutParam()),
561 RTEXITCODE_FAILURE);
562 showProgress(pProgress);
563 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Failed to list Vnic attachments")), RTEXITCODE_FAILURE);
564
565 CHECK_ERROR2_RET(hrc,
566 pVnicAttachmentIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVnicAttachmentIds)),
567 RTEXITCODE_FAILURE);
568 CHECK_ERROR2_RET(hrc,
569 pVnicIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVnicIds)),
570 RTEXITCODE_FAILURE);
571
572 RTPrintf(Cloud::tr("The list of the Vnic attachments:\n"));
573 size_t cVnicAttchIds = arrayVnicAttachmentIds.size();
574 size_t cVnicIds = arrayVnicIds.size();
575
576 if (cVnicAttchIds == 0)
577 RTPrintf(Cloud::tr("\tEmpty\n"));
578 else
579 {
580 Bstr value;
581 for (size_t k = 0; k < cVnicAttchIds; k++)
582 {
583 if (k < cVnicIds)
584 value = arrayVnicIds[k];
585 RTPrintf(Cloud::tr("Vnic attachment id [%ls]:\n\t Vnic id - %ls\n"), arrayVnicAttachmentIds[k], value.raw());
586 }
587 }
588
589 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
590}
591
592
593/**
[77883]594 * General function which handles the "list" commands
595 *
596 * @returns RTEXITCODE
[77885]597 * @param a is the list of passed arguments
598 * @param iFirst is the position of the first unparsed argument in the arguments list
599 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
[77883]600 * arguments which have been already parsed before
601 */
602static RTEXITCODE handleCloudLists(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
603{
[91133]604 enum
605 {
606 kCloudListIota = 1000,
607 kCloudList_Images,
608 kCloudList_Instances,
609 kCloudList_Machines,
610 kCloudList_Networks,
611 kCloudList_Objects,
612 kCloudList_Subnets,
613 kCloudList_Vcns,
[98852]614 kCloudList_VnicAttachments,
[91133]615 };
616
617 static const RTGETOPTDEF s_aOptions[] =
618 {
619 { "images", kCloudList_Images, RTGETOPT_REQ_NOTHING },
620 { "instances", kCloudList_Instances, RTGETOPT_REQ_NOTHING },
621 { "machines", kCloudList_Machines, RTGETOPT_REQ_NOTHING },
622 { "networks", kCloudList_Networks, RTGETOPT_REQ_NOTHING },
623 { "objects", kCloudList_Objects, RTGETOPT_REQ_NOTHING },
624 { "subnets", kCloudList_Subnets, RTGETOPT_REQ_NOTHING },
625 { "vcns", kCloudList_Vcns, RTGETOPT_REQ_NOTHING },
[91154]626 { "vms", kCloudList_Machines, RTGETOPT_REQ_NOTHING },
[98852]627 { "vnicattachments", kCloudList_VnicAttachments, RTGETOPT_REQ_NOTHING },
[91133]628
629 { "help", 'h', RTGETOPT_REQ_NOTHING },
630 { "-?", 'h', RTGETOPT_REQ_NOTHING },
631 { "-help", 'h', RTGETOPT_REQ_NOTHING },
632 { "--help", 'h', RTGETOPT_REQ_NOTHING },
633 };
634
[83279]635 if (a->argc == iFirst)
636 {
[92372]637 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]638 printHelp(g_pStdOut);
639 return RTEXITCODE_SUCCESS;
640 }
[77883]641
642 RTGETOPTSTATE GetState;
643 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
644 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
645
646 int c;
647 RTGETOPTUNION ValueUnion;
648 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
649 {
650 switch (c)
651 {
[91133]652 case kCloudList_Images:
[99513]653 setCurrentSubcommand(HELP_SCOPE_CLOUD_LIST_IMAGES);
[77883]654 return listCloudImages(a, GetState.iNext, pCommonOpts);
[91133]655
656 case kCloudList_Instances:
[99513]657 setCurrentSubcommand(HELP_SCOPE_CLOUD_LIST_INSTANCES);
[77883]658 return listCloudInstances(a, GetState.iNext, pCommonOpts);
[91133]659 case kCloudList_Machines:
[90214]660 return listCloudMachines(a, GetState.iNext,
[90220]661 pCommonOpts->provider.pszProviderName,
662 pCommonOpts->profile.pszProfileName);
[90214]663
[98852]664 case kCloudList_VnicAttachments:
[99513]665 setCurrentSubcommand(HELP_SCOPE_CLOUD_LIST_VNICATTACHMENTS);
[98852]666 return listCloudVnicAttachments(a, GetState.iNext, pCommonOpts);
667
[91133]668 case 'h':
669 printHelp(g_pStdOut);
670 return RTEXITCODE_SUCCESS;
671
[77883]672 case VINF_GETOPT_NOT_OPTION:
673 return errorUnknownSubcommand(ValueUnion.psz);
674
675 default:
676 return errorGetOpt(c, &ValueUnion);
677 }
678 }
679
680 return errorNoSubcommand();
681}
682
[98852]683
[78734]684static RTEXITCODE createCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
685{
[80939]686 HRESULT hrc = S_OK;
687
[93875]688 enum
689 {
690 kInstanceIota = 1000,
691 kInstance_ShapeCpu,
692 kInstance_ShapeMemory,
693 };
694
[80939]695 static const RTGETOPTDEF s_aOptions[] =
696 {
697 { "--image-id", 'i', RTGETOPT_REQ_STRING },
[81084]698 { "--boot-volume-id", 'v', RTGETOPT_REQ_STRING },
[80939]699 { "--display-name", 'n', RTGETOPT_REQ_STRING },
700 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
701 { "--shape", 's', RTGETOPT_REQ_STRING },
[93875]702 { "--shape-cpus", kInstance_ShapeCpu, RTGETOPT_REQ_UINT32 },
703 { "--shape-memory", kInstance_ShapeMemory, RTGETOPT_REQ_UINT32 },
[80939]704 { "--domain-name", 'd', RTGETOPT_REQ_STRING },
705 { "--boot-disk-size", 'b', RTGETOPT_REQ_STRING },
706 { "--publicip", 'p', RTGETOPT_REQ_STRING },
707 { "--subnet", 't', RTGETOPT_REQ_STRING },
708 { "--privateip", 'P', RTGETOPT_REQ_STRING },
[80948]709 { "--launch", 'l', RTGETOPT_REQ_STRING },
[81398]710 { "--public-ssh-key", 'k', RTGETOPT_REQ_STRING },
[87278]711 { "--cloud-init-script-path", 'c', RTGETOPT_REQ_STRING },
[93872]712 { "help", 'h', RTGETOPT_REQ_NOTHING },
713 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[80939]714 };
715 RTGETOPTSTATE GetState;
716 RTGETOPTUNION ValueUnion;
717 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
718 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]719 if (a->argc == iFirst)
720 {
[92372]721 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]722 printHelp(g_pStdOut);
723 return RTEXITCODE_SUCCESS;
724 }
[80939]725
726 ComPtr<IAppliance> pAppliance;
727 CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE);
728 ULONG vsdNum = 1;
729 CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(1, &vsdNum), RTEXITCODE_FAILURE);
730 com::SafeIfaceArray<IVirtualSystemDescription> virtualSystemDescriptions;
731 CHECK_ERROR2_RET(hrc, pAppliance,
732 COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(virtualSystemDescriptions)),
733 RTEXITCODE_FAILURE);
734 ComPtr<IVirtualSystemDescription> pVSD = virtualSystemDescriptions[0];
735
[81398]736 Utf8Str strDisplayName, strImageId, strBootVolumeId, strPublicSSHKey;
[80939]737 int c;
738 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
739 {
740 switch (c)
741 {
742 case 'i':
743 strImageId = ValueUnion.psz;
744 pVSD->AddDescription(VirtualSystemDescriptionType_CloudImageId,
[82369]745 Bstr(ValueUnion.psz).raw(), NULL);
[80939]746 break;
[81084]747
748 case 'v':
749 strBootVolumeId = ValueUnion.psz;
750 pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootVolumeId,
[82369]751 Bstr(ValueUnion.psz).raw(), NULL);
[81084]752 break;
[80939]753 case 'n':
754 strDisplayName = ValueUnion.psz;
755 pVSD->AddDescription(VirtualSystemDescriptionType_Name,
[82369]756 Bstr(ValueUnion.psz).raw(), NULL);
[80939]757 break;
758 case 'm':
759 pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCILaunchMode,
[82369]760 Bstr(ValueUnion.psz).raw(), NULL);
[80939]761 break;
[93875]762
[80939]763 case 's':
764 pVSD->AddDescription(VirtualSystemDescriptionType_CloudInstanceShape,
[82369]765 Bstr(ValueUnion.psz).raw(), NULL);
[80939]766 break;
[93875]767
768 case kInstance_ShapeCpu:
769 pVSD->AddDescription(VirtualSystemDescriptionType_CloudShapeCpus,
770 BstrFmt("%RI32", ValueUnion.u32).raw(), NULL);
771 break;
772
773 case kInstance_ShapeMemory:
774 pVSD->AddDescription(VirtualSystemDescriptionType_CloudShapeMemory,
775 BstrFmt("%RI32", ValueUnion.u32).raw(), NULL);
776 break;
777
[80939]778 case 'd':
779 pVSD->AddDescription(VirtualSystemDescriptionType_CloudDomain,
[82369]780 Bstr(ValueUnion.psz).raw(), NULL);
[80939]781 break;
782 case 'b':
783 pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootDiskSize,
[82369]784 Bstr(ValueUnion.psz).raw(), NULL);
[80939]785 break;
786 case 'p':
787 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicIP,
[82369]788 Bstr(ValueUnion.psz).raw(), NULL);
[80939]789 break;
790 case 'P':
791 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPrivateIP,
[82369]792 Bstr(ValueUnion.psz).raw(), NULL);
[80939]793 break;
794 case 't':
795 pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCISubnet,
[82369]796 Bstr(ValueUnion.psz).raw(), NULL);
[80939]797 break;
[80948]798 case 'l':
799 {
800 Utf8Str strLaunch(ValueUnion.psz);
801 if (strLaunch.isNotEmpty() && (strLaunch.equalsIgnoreCase("true") || strLaunch.equalsIgnoreCase("false")))
802 pVSD->AddDescription(VirtualSystemDescriptionType_CloudLaunchInstance,
[82369]803 Bstr(ValueUnion.psz).raw(), NULL);
[80948]804 break;
805 }
[81398]806 case 'k':
807 strPublicSSHKey = ValueUnion.psz;
808 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicSSHKey,
[82369]809 Bstr(ValueUnion.psz).raw(), NULL);
[81398]810 break;
[87278]811 case 'c':
812 pVSD->AddDescription(VirtualSystemDescriptionType_CloudInitScriptPath,
813 Bstr(ValueUnion.psz).raw(), NULL);
814 break;
[93872]815 case 'h':
[83279]816 printHelp(g_pStdOut);
817 return RTEXITCODE_SUCCESS;
[80939]818 case VINF_GETOPT_NOT_OPTION:
819 return errorUnknownSubcommand(ValueUnion.psz);
820 default:
821 return errorGetOpt(c, &ValueUnion);
822 }
823 }
824
[83279]825 /* Delayed check. It allows us to print help information.*/
826 hrc = checkAndSetCommonOptions(a, pCommonOpts);
827 if (FAILED(hrc))
828 return RTEXITCODE_FAILURE;
829
[86714]830 if (strPublicSSHKey.isEmpty())
[92372]831 RTPrintf(Cloud::tr("Warning!!! Public SSH key doesn't present in the passed arguments...\n"));
[81398]832
[81084]833 if (strImageId.isNotEmpty() && strBootVolumeId.isNotEmpty())
[92372]834 return errorArgument(Cloud::tr("Parameters --image-id and --boot-volume-id are mutually exclusive. "
835 "Only one of them must be presented."));
[80939]836
[81084]837 if (strImageId.isEmpty() && strBootVolumeId.isEmpty())
[92372]838 return errorArgument(Cloud::tr("Missing parameter --image-id or --boot-volume-id. One of them must be presented."));
[81084]839
[80939]840 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
841
842 pVSD->AddDescription(VirtualSystemDescriptionType_CloudProfileName,
843 Bstr(pCommonOpts->profile.pszProfileName).raw(),
[82369]844 NULL);
[80939]845
846 ComObjPtr<ICloudClient> oCloudClient;
847 CHECK_ERROR2_RET(hrc, pCloudProfile,
848 CreateCloudClient(oCloudClient.asOutParam()),
849 RTEXITCODE_FAILURE);
850
851 ComPtr<IStringArray> infoArray;
852 com::SafeArray<BSTR> pStrInfoArray;
853 ComPtr<IProgress> pProgress;
854
855#if 0
856 /*
857 * OCI API returns an error during an instance creation if the image isn't available
858 * or in the inappropriate state. So the check can be omitted.
859 */
[92372]860 RTPrintf(Cloud::tr("Checking the cloud image with id \'%s\'...\n"), strImageId.c_str());
[80939]861 CHECK_ERROR2_RET(hrc, oCloudClient,
862 GetImageInfo(Bstr(strImageId).raw(),
863 infoArray.asOutParam(),
864 pProgress.asOutParam()),
865 RTEXITCODE_FAILURE);
866
867 hrc = showProgress(pProgress);
[92372]868 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Checking the cloud image failed")), RTEXITCODE_FAILURE);
[80939]869
870 pProgress.setNull();
871#endif
872
[81084]873 if (strImageId.isNotEmpty())
[92372]874 RTPrintf(Cloud::tr("Creating cloud instance with name \'%s\' from the image \'%s\'...\n"),
[81084]875 strDisplayName.c_str(), strImageId.c_str());
876 else
[92372]877 RTPrintf(Cloud::tr("Creating cloud instance with name \'%s\' from the boot volume \'%s\'...\n"),
[81084]878 strDisplayName.c_str(), strBootVolumeId.c_str());
[80939]879
880 CHECK_ERROR2_RET(hrc, oCloudClient, LaunchVM(pVSD, pProgress.asOutParam()), RTEXITCODE_FAILURE);
881
882 hrc = showProgress(pProgress);
[92372]883 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Creating cloud instance failed")), RTEXITCODE_FAILURE);
[80939]884
885 if (SUCCEEDED(hrc))
[92372]886 RTPrintf(Cloud::tr("Cloud instance was created successfully\n"));
[80939]887
888 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
[78734]889}
890
[100808]891
892static RTEXITCODE cloneCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
893{
894 HRESULT hrc = S_OK;
895
896 enum
897 {
898 kInstanceIota = 1000,
899 kInstance_ShapeCpu,
900 kInstance_ShapeMemory,
901 };
902
903 static const RTGETOPTDEF s_aOptions[] =
904 {
905 { "--id", 'i', RTGETOPT_REQ_STRING },
906 { "--clone-name", 'n', RTGETOPT_REQ_STRING },
907
908 { "help", 'h', RTGETOPT_REQ_NOTHING },
909 { "--help", 'h', RTGETOPT_REQ_NOTHING }
910 };
911 RTGETOPTSTATE GetState;
912 RTGETOPTUNION ValueUnion;
913 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
914 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
915 if (a->argc == iFirst)
916 {
917 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
918 printHelp(g_pStdOut);
919 return RTEXITCODE_SUCCESS;
920 }
921
922 Utf8Str strCloneName, strInstanceId;
923 int c;
924 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
925 {
926 switch (c)
927 {
928 case 'i':
929 strInstanceId = ValueUnion.psz;
930
931 break;
932 case 'n':
933 strCloneName = ValueUnion.psz;
934 break;
935 case 'h':
936 printHelp(g_pStdOut);
937 return RTEXITCODE_SUCCESS;
938 case VINF_GETOPT_NOT_OPTION:
939 return errorUnknownSubcommand(ValueUnion.psz);
940 default:
941 return errorGetOpt(c, &ValueUnion);
942 }
943 }
944
945 /* Delayed check. It allows us to print help information.*/
946 hrc = checkAndSetCommonOptions(a, pCommonOpts);
947 if (FAILED(hrc))
948 return RTEXITCODE_FAILURE;
949
950 if (strInstanceId.isEmpty())
951 return errorArgument(Cloud::tr("Missing parameter --id."));
952
953// if (strCloneName.isEmpty())
954// return errorArgument(Cloud::tr("Missing parameter --clone-name."));
955
956 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
957
958 ComObjPtr<ICloudClient> oCloudClient;
959 CHECK_ERROR2_RET(hrc, pCloudProfile,
960 CreateCloudClient(oCloudClient.asOutParam()),
961 RTEXITCODE_FAILURE);
962
963 ComPtr<IProgress> pProgress;
964 ComPtr<ICloudMachine> pClonedMachine;
965
966 RTPrintf(Cloud::tr("Cloning cloud instance with Id \'%s\'...\n"), strInstanceId.c_str());
967
968 CHECK_ERROR2_RET(hrc, oCloudClient, CloneInstance(Bstr(strInstanceId).raw(),
969 Bstr(strCloneName).raw(),
970 pClonedMachine.asOutParam(),
971 pProgress.asOutParam()), RTEXITCODE_FAILURE);
972
973 hrc = showProgress(pProgress);
974 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Cloning cloud instance failed")), RTEXITCODE_FAILURE);
975
976 Bstr strAttr;
977 pClonedMachine->COMGETTER(Id)(strAttr.asOutParam());
978 RTPrintf(Cloud::tr("Cloned instance UUID in VirtualBox: %ls\n"), strAttr.raw());
979 strAttr.setNull();
980 pClonedMachine->COMGETTER(Name)(strAttr.asOutParam());
981 RTPrintf(Cloud::tr("Cloned instance name: %ls\n"), strAttr.raw());
982
983 if (SUCCEEDED(hrc))
984 RTPrintf(Cloud::tr("Cloud instance was cloned successfully\n"));
985
986 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
987}
988
[78734]989static RTEXITCODE updateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
990{
[78735]991 RT_NOREF(a);
[78734]992 RT_NOREF(iFirst);
993 RT_NOREF(pCommonOpts);
994 return RTEXITCODE_SUCCESS;
995}
996
997static RTEXITCODE showCloudInstanceInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
998{
999 HRESULT hrc = S_OK;
1000
1001 static const RTGETOPTDEF s_aOptions[] =
1002 {
[83279]1003 { "--id", 'i', RTGETOPT_REQ_STRING },
[93872]1004 { "help", 'h', RTGETOPT_REQ_NOTHING },
1005 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[78734]1006 };
1007 RTGETOPTSTATE GetState;
1008 RTGETOPTUNION ValueUnion;
1009 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1010 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]1011 if (a->argc == iFirst)
1012 {
[92372]1013 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]1014 printHelp(g_pStdOut);
1015 return RTEXITCODE_SUCCESS;
1016 }
[78734]1017
1018 Utf8Str strInstanceId;
[79980]1019
[78734]1020 int c;
1021 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1022 {
1023 switch (c)
1024 {
1025 case 'i':
[79980]1026 {
1027 if (strInstanceId.isNotEmpty())
[92372]1028 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
[79980]1029
1030 strInstanceId = ValueUnion.psz;
1031 if (strInstanceId.isEmpty())
[92372]1032 return errorArgument(Cloud::tr("Empty parameter: --id"));
[79980]1033
[78734]1034 break;
[79980]1035 }
[93872]1036 case 'h':
[83279]1037 printHelp(g_pStdOut);
1038 return RTEXITCODE_SUCCESS;
[78734]1039 case VINF_GETOPT_NOT_OPTION:
1040 return errorUnknownSubcommand(ValueUnion.psz);
[79980]1041
[78734]1042 default:
1043 return errorGetOpt(c, &ValueUnion);
1044 }
1045 }
1046
[83279]1047 /* Delayed check. It allows us to print help information.*/
1048 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1049 if (FAILED(hrc))
1050 return RTEXITCODE_FAILURE;
1051
[79980]1052 if (strInstanceId.isEmpty())
[92372]1053 return errorArgument(Cloud::tr("Missing parameter: --id"));
[79980]1054
[78734]1055 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1056
1057 ComObjPtr<ICloudClient> oCloudClient;
1058 CHECK_ERROR2_RET(hrc, pCloudProfile,
1059 CreateCloudClient(oCloudClient.asOutParam()),
1060 RTEXITCODE_FAILURE);
[92372]1061 RTPrintf(Cloud::tr("Getting information about cloud instance with id %s...\n"), strInstanceId.c_str());
1062 RTPrintf(Cloud::tr("Reply is in the form \'setting name\' = \'value\'\n"));
[78734]1063
1064 ComPtr<IAppliance> pAppliance;
1065 CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE);
1066
1067 com::SafeIfaceArray<IVirtualSystemDescription> vsdArray;
[78736]1068 ULONG requestedVSDnums = 1;
1069 ULONG newVSDnums = 0;
[78734]1070 CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(requestedVSDnums, &newVSDnums), RTEXITCODE_FAILURE);
1071 if (requestedVSDnums != newVSDnums)
1072 return RTEXITCODE_FAILURE;
1073
1074 CHECK_ERROR2_RET(hrc, pAppliance, COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(vsdArray)), RTEXITCODE_FAILURE);
1075 ComPtr<IVirtualSystemDescription> instanceDescription = vsdArray[0];
[78841]1076
1077 ComPtr<IProgress> progress;
[78734]1078 CHECK_ERROR2_RET(hrc, oCloudClient,
[79943]1079 GetInstanceInfo(Bstr(strInstanceId).raw(), instanceDescription, progress.asOutParam()),
[78734]1080 RTEXITCODE_FAILURE);
[78841]1081
1082 hrc = showProgress(progress);
[92372]1083 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Getting information about cloud instance failed")), RTEXITCODE_FAILURE);
[78841]1084
[92372]1085 RTPrintf(Cloud::tr("Cloud instance info (provider '%s'):\n"),
[78734]1086 pCommonOpts->provider.pszProviderName);
1087
1088 struct vsdHReadable {
1089 VirtualSystemDescriptionType_T vsdType;
1090 Utf8Str strFound;
1091 Utf8Str strNotFound;
1092 };
1093
[98778]1094 const size_t vsdHReadableArraySize = 15;//the number of items in the vsdHReadableArray
[81421]1095 vsdHReadable vsdHReadableArray[vsdHReadableArraySize] = {
[92372]1096 {VirtualSystemDescriptionType_CloudDomain, Cloud::tr("Availability domain = %ls\n"), Cloud::tr("Availability domain wasn't found\n")},
1097 {VirtualSystemDescriptionType_Name, Cloud::tr("Instance displayed name = %ls\n"), Cloud::tr("Instance displayed name wasn't found\n")},
1098 {VirtualSystemDescriptionType_CloudInstanceState, Cloud::tr("Instance state = %ls\n"), Cloud::tr("Instance state wasn't found\n")},
1099 {VirtualSystemDescriptionType_CloudInstanceId, Cloud::tr("Instance Id = %ls\n"), Cloud::tr("Instance Id wasn't found\n")},
1100 {VirtualSystemDescriptionType_CloudInstanceDisplayName, Cloud::tr("Instance name = %ls\n"), Cloud::tr("Instance name wasn't found\n")},
1101 {VirtualSystemDescriptionType_CloudImageId, Cloud::tr("Bootable image Id = %ls\n"),
1102 Cloud::tr("Image Id whom the instance is booted up wasn't found\n")},
1103 {VirtualSystemDescriptionType_CloudInstanceShape, Cloud::tr("Shape of the instance = %ls\n"),
1104 Cloud::tr("The shape of the instance wasn't found\n")},
1105 {VirtualSystemDescriptionType_OS, Cloud::tr("Type of guest OS = %ls\n"), Cloud::tr("Type of guest OS wasn't found\n")},
1106 {VirtualSystemDescriptionType_Memory, Cloud::tr("RAM = %ls MB\n"), Cloud::tr("Value for RAM wasn't found\n")},
1107 {VirtualSystemDescriptionType_CPU, Cloud::tr("CPUs = %ls\n"), Cloud::tr("Numbers of CPUs weren't found\n")},
1108 {VirtualSystemDescriptionType_CloudPublicIP, Cloud::tr("Instance public IP = %ls\n"), Cloud::tr("Public IP wasn't found\n")},
[98778]1109 {VirtualSystemDescriptionType_Miscellaneous, "%ls\n", Cloud::tr("Miscellanious wasn't found\n")},
1110 {VirtualSystemDescriptionType_CloudInstanceFreeFormTags, "%ls\n", Cloud::tr("Free-form tags weren't found\n")},
1111 {VirtualSystemDescriptionType_CloudInstanceMetadata, "%ls\n", Cloud::tr("Metadata was't found\n")},
1112 {VirtualSystemDescriptionType_CloudInitScriptPath, "Cloud-init script: \n\t%ls\n", Cloud::tr("Cloud-init script wasn't found\n")}
[78734]1113 };
1114
1115 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
1116 com::SafeArray<BSTR> aRefs;
1117 com::SafeArray<BSTR> aOvfValues;
1118 com::SafeArray<BSTR> aVBoxValues;
1119 com::SafeArray<BSTR> aExtraConfigValues;
1120
1121 for (size_t i=0; i<vsdHReadableArraySize ; ++i)
1122 {
1123 hrc = instanceDescription->GetDescriptionByType(vsdHReadableArray[i].vsdType,
1124 ComSafeArrayAsOutParam(retTypes),
1125 ComSafeArrayAsOutParam(aRefs),
1126 ComSafeArrayAsOutParam(aOvfValues),
1127 ComSafeArrayAsOutParam(aVBoxValues),
1128 ComSafeArrayAsOutParam(aExtraConfigValues));
1129 if (FAILED(hrc) || aVBoxValues.size() == 0)
1130 LogRel((vsdHReadableArray[i].strNotFound.c_str()));
1131 else
[81421]1132 {
1133 LogRel(("Size is %d", aVBoxValues.size()));
1134 for (size_t j = 0; j<aVBoxValues.size(); ++j)
1135 {
1136 RTPrintf(vsdHReadableArray[i].strFound.c_str(), aVBoxValues[j]);
1137 }
1138 }
[78734]1139
1140 retTypes.setNull();
1141 aRefs.setNull();
1142 aOvfValues.setNull();
1143 aVBoxValues.setNull();
1144 aExtraConfigValues.setNull();
1145 }
1146
1147 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1148}
1149
[102095]1150
1151static RTEXITCODE cloudInstanceMetricList(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1152{
1153 HRESULT hrc = S_OK;
1154
1155 static const RTGETOPTDEF s_aOptions[] =
1156 {
1157 { "--id", 'i', RTGETOPT_REQ_STRING },
1158 { "help", 'h', RTGETOPT_REQ_NOTHING },
1159 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1160 };
1161 RTGETOPTSTATE GetState;
1162 RTGETOPTUNION ValueUnion;
1163 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1164 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1165 if (a->argc == iFirst)
1166 {
1167 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1168 printHelp(g_pStdOut);
1169 return RTEXITCODE_SUCCESS;
1170 }
1171
1172 Utf8Str strInstanceId;
1173
1174 int c;
1175 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1176 {
1177 switch (c)
1178 {
1179 case 'i':
1180 {
1181 if (strInstanceId.isNotEmpty())
1182 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
1183
1184 strInstanceId = ValueUnion.psz;
1185 if (strInstanceId.isEmpty())
1186 return errorArgument(Cloud::tr("Empty parameter: --id"));
1187
1188 break;
1189 }
1190 case 'h':
1191 printHelp(g_pStdOut);
1192 return RTEXITCODE_SUCCESS;
1193 case VINF_GETOPT_NOT_OPTION:
1194 return errorUnknownSubcommand(ValueUnion.psz);
1195
1196 default:
1197 return errorGetOpt(c, &ValueUnion);
1198 }
1199 }
1200
1201 /* Delayed check. It allows us to print help information.*/
1202 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1203 if (FAILED(hrc))
1204 return RTEXITCODE_FAILURE;
1205
1206 if (strInstanceId.isEmpty())
1207 return errorArgument(Cloud::tr("Missing parameter: --id"));
1208
1209 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1210
1211 ComObjPtr<ICloudClient> oCloudClient;
1212 CHECK_ERROR2_RET(hrc, pCloudProfile,
1213 CreateCloudClient(oCloudClient.asOutParam()),
1214 RTEXITCODE_FAILURE);
1215 RTPrintf(Cloud::tr("Getting list of metric names for the cloud instance with id %s\n"), strInstanceId.c_str());
1216 RTPrintf(Cloud::tr("Reply is the list, each metric name is placed on a separate line as \' - <metric name>\'\n"));
1217
1218 ComPtr<IProgress> progress;
1219
1220 CHECK_ERROR2_RET(hrc, oCloudClient, ReadCloudMachineList(progress.asOutParam()), RTEXITCODE_FAILURE);
1221
1222 /* First step*/
1223 RTPrintf(Cloud::tr("First, reading the cloud machines list...\n"));
1224 hrc = showProgress(progress);
1225 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Reading the cloud machines list failed")), RTEXITCODE_FAILURE);
1226
1227 com::SafeIfaceArray<ICloudMachine> aMachines;
[102099]1228 CHECK_ERROR2_RET(hrc, oCloudClient,
[102095]1229 COMGETTER(CloudMachineList)(ComSafeArrayAsOutParam(aMachines)),
1230 RTEXITCODE_FAILURE);
1231
1232 const size_t cMachines = aMachines.size();
1233 if (cMachines == 0)
1234 return RTEXITCODE_SUCCESS;
1235
1236 std::vector<ComPtr<ICloudMachine> > vMachines(cMachines);
1237 std::vector<com::Bstr> vBstrCloudIds(cMachines);
1238 std::vector<com::Bstr> vBstrIds(cMachines);
1239
1240 com::Bstr bstrFoundMachineVBoxId;
1241
1242 for (size_t i = 0; i < cMachines; ++i)
1243 {
1244 vMachines[i] = aMachines[i];
1245
1246 CHECK_ERROR2_RET(hrc, vMachines[i],
1247 COMGETTER(CloudId)(vBstrCloudIds[i].asOutParam()),
1248 RTEXITCODE_FAILURE);
1249
1250 Utf8Str strCurrMachineCloudId(vBstrCloudIds[i]);
1251 if (strCurrMachineCloudId.equals(strInstanceId))
1252 {
1253 CHECK_ERROR2_RET(hrc, vMachines[i],
1254 COMGETTER(Id)(vBstrIds[i].asOutParam()),
1255 RTEXITCODE_FAILURE);
1256 bstrFoundMachineVBoxId = vBstrIds[i];
1257 break;
1258 }
1259 }
1260
1261 if (bstrFoundMachineVBoxId.isEmpty())
1262 {
1263 RTPrintf("The passed cloud instance Id \'%s\' WASN'T found among the cloud machines "
[102099]1264 "of user \'%s\' registered with VirtualBox\n",
[102095]1265 strInstanceId.c_str(), pCommonOpts->profile.pszProfileName);
1266 return RTEXITCODE_FAILURE;
1267 }
1268
1269 /* Second step*/
1270 RTPrintf(Cloud::tr("Second, refresh information about cloud instance ...\n"));
1271 ComPtr<ICloudMachine> pMachine;
1272 CHECK_ERROR2_RET(hrc, oCloudClient,
1273 GetCloudMachine(bstrFoundMachineVBoxId.raw(), pMachine.asOutParam()), RTEXITCODE_FAILURE);
1274
1275 ComPtr<IProgress> pRefreshProgress;
1276 CHECK_ERROR2_RET(hrc, pMachine, Refresh(pRefreshProgress.asOutParam()), RTEXITCODE_FAILURE);
1277
1278 hrc = showProgress(pRefreshProgress);
1279 CHECK_PROGRESS_ERROR_RET(pRefreshProgress, (Cloud::tr("Refreshing information about cloud instance failed")), RTEXITCODE_FAILURE);
1280
1281 /* Third step*/
1282 RTPrintf(Cloud::tr("Third, getting information about cloud instance metric names...\n"));
1283 ComPtr<IProgress> progress2;
1284 ComPtr<IStringArray> returnMetricNames;
1285 CHECK_ERROR2_RET(hrc, pMachine, ListMetricNames(returnMetricNames.asOutParam(), progress2.asOutParam()), RTEXITCODE_FAILURE);
1286
1287 hrc = showProgress(progress2);
1288 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Getting information about cloud instance metrics failed")), RTEXITCODE_FAILURE);
1289
1290 com::SafeArray<BSTR> metricNamesArray;
1291 CHECK_ERROR2_RET(hrc,
1292 returnMetricNames, COMGETTER(Values)(ComSafeArrayAsOutParam(metricNamesArray)),
1293 RTEXITCODE_FAILURE);
1294
1295 RTPrintf(Cloud::tr("Available metric names:\n"));
[102097]1296 size_t cMetricNamesArraySize = metricNamesArray.size();
[102095]1297
1298 if (cMetricNamesArraySize == 0)
1299 {
1300 RTPrintf(Cloud::tr("\tThe list of metric names is empty. It may mean that an appropriate service wasn't run on the instance.\n"));
1301 return RTEXITCODE_FAILURE;
1302 }
1303 else
1304 {
1305 Bstr value;
[102097]1306 for (size_t k = 0; k < cMetricNamesArraySize; ++k)
[102095]1307 {
1308 value = metricNamesArray[k];
1309 MetricType_T aMetricType;
1310 CHECK_ERROR2_RET(hrc, oCloudClient, GetMetricTypeByName(value.raw(), &aMetricType), RTEXITCODE_FAILURE);
1311
1312 if (SUCCEEDED(hrc))
[102637]1313 RTPrintf(Cloud::tr(" - %ls\n"), value.raw());
[102095]1314 }
1315 }
1316
1317 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1318}
1319
1320
1321static RTEXITCODE cloudInstanceMetricData(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1322{
1323 HRESULT hrc = S_OK;
1324
1325 static const RTGETOPTDEF s_aOptions[] =
1326 {
1327 { "--id", 'i', RTGETOPT_REQ_STRING },
1328 { "--metric-name", 'n', RTGETOPT_REQ_STRING },
1329 { "--metric-points",'p', RTGETOPT_REQ_STRING },
1330 { "help", 'h', RTGETOPT_REQ_NOTHING },
1331 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1332 };
1333 RTGETOPTSTATE GetState;
1334 RTGETOPTUNION ValueUnion;
1335 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1336 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1337 if (a->argc == iFirst)
1338 {
1339 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1340 printHelp(g_pStdOut);
1341 return RTEXITCODE_SUCCESS;
1342 }
1343
1344 Utf8Str strInstanceId;
1345 Utf8Str strMetricName;
1346 Utf8Str strMetricPoints;
1347
1348 int c;
1349 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1350 {
1351 switch (c)
1352 {
1353 case 'i':
1354 {
1355 if (strInstanceId.isNotEmpty())
1356 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
1357
1358 strInstanceId = ValueUnion.psz;
1359 if (strInstanceId.isEmpty())
1360 return errorArgument(Cloud::tr("Empty parameter: --id"));
1361
1362 break;
1363 }
1364 case 'n':
1365 {
1366 if (strMetricName.isNotEmpty())
1367 return errorArgument(Cloud::tr("Duplicate parameter: --metric-name"));
1368
1369 strMetricName = ValueUnion.psz;
1370 if (strMetricName.isEmpty())
1371 return errorArgument(Cloud::tr("Empty parameter: --metric-name"));
1372
1373 break;
1374 }
1375 case 'p':
1376 {
1377 if (strMetricPoints.isNotEmpty())
1378 return errorArgument(Cloud::tr("Duplicate parameter: --metric-points"));
1379
1380 strMetricPoints = ValueUnion.psz;
1381 if (strMetricPoints.isEmpty())
1382 return errorArgument(Cloud::tr("Empty parameter: --metric-points"));
1383
1384 break;
1385 }
1386 case 'h':
1387 printHelp(g_pStdOut);
1388 return RTEXITCODE_SUCCESS;
1389 case VINF_GETOPT_NOT_OPTION:
1390 return errorUnknownSubcommand(ValueUnion.psz);
1391
1392 default:
1393 return errorGetOpt(c, &ValueUnion);
1394 }
1395 }
1396
1397 /* Delayed check. It allows us to print help information.*/
1398 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1399 if (FAILED(hrc))
1400 return RTEXITCODE_FAILURE;
1401
1402 if (strInstanceId.isEmpty())
1403 return errorArgument(Cloud::tr("Missing parameter: --id"));
1404 if (strMetricName.isEmpty())
1405 return errorArgument(Cloud::tr("Missing parameter: --metric-name"));
1406
1407 unsigned long metricPoins;
1408 strMetricPoints.isEmpty() ? metricPoins = 1 : metricPoins = RTStrToUInt32(strMetricPoints.c_str());
1409
1410 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1411
1412 ComObjPtr<ICloudClient> oCloudClient;
1413 CHECK_ERROR2_RET(hrc, pCloudProfile,
1414 CreateCloudClient(oCloudClient.asOutParam()),
1415 RTEXITCODE_FAILURE);
1416 RTPrintf(Cloud::tr("Getting %s metric for the cloud instance with id %s...\n"), strMetricName.c_str(), strInstanceId.c_str());
1417 RTPrintf(Cloud::tr("Reply is in the form \'%s[Rfc2822 time format]\' = \'value\'\n"), strMetricName.c_str());
1418
1419 /* Check the requested metric type */
1420 MetricType_T aMetricType;
1421 CHECK_ERROR2_RET(hrc, oCloudClient, GetMetricTypeByName(com::Bstr(strMetricName.c_str()).raw(), &aMetricType), RTEXITCODE_FAILURE);
1422
1423 /* First step*/
1424 RTPrintf(Cloud::tr("First, reading the cloud machines list...\n"));
1425 ComPtr<IProgress> progress;
1426 CHECK_ERROR2_RET(hrc, oCloudClient, ReadCloudMachineList(progress.asOutParam()), RTEXITCODE_FAILURE);
1427
1428 hrc = showProgress(progress);
1429 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Reading the cloud machines list failed")), RTEXITCODE_FAILURE);
1430
1431 com::SafeIfaceArray<ICloudMachine> aMachines;
[102100]1432 CHECK_ERROR2_RET(hrc, oCloudClient,
[102095]1433 COMGETTER(CloudMachineList)(ComSafeArrayAsOutParam(aMachines)),
1434 RTEXITCODE_FAILURE);
1435
1436 const size_t cMachines = aMachines.size();
1437 if (cMachines == 0)
1438 return RTEXITCODE_SUCCESS;
1439
1440 std::vector<ComPtr<ICloudMachine> > vMachines(cMachines);
1441 std::vector<com::Bstr> vBstrCloudIds(cMachines);
1442 std::vector<com::Bstr> vBstrIds(cMachines);
1443
1444 com::Bstr bstrFoundMachineVBoxId;
1445
1446 for (size_t i = 0; i < cMachines; ++i)
1447 {
1448 vMachines[i] = aMachines[i];
1449
1450 CHECK_ERROR2_RET(hrc, vMachines[i],
1451 COMGETTER(CloudId)(vBstrCloudIds[i].asOutParam()),
1452 RTEXITCODE_FAILURE);
1453
1454 Utf8Str strCurrMachineCloudId(vBstrCloudIds[i]);
1455 if (strCurrMachineCloudId.equals(strInstanceId))
1456 {
1457 CHECK_ERROR2_RET(hrc, vMachines[i],
1458 COMGETTER(Id)(vBstrIds[i].asOutParam()),
1459 RTEXITCODE_FAILURE);
1460 bstrFoundMachineVBoxId = vBstrIds[i];
1461 break;
1462 }
1463 }
1464
1465 if (bstrFoundMachineVBoxId.isEmpty())
1466 {
1467 RTPrintf("The passed cloud instance Id \'%s\' WASN'T found among the cloud machines "
[102099]1468 "of user \'%s\' registered with VirtualBox\n",
[102095]1469 strInstanceId.c_str(), pCommonOpts->profile.pszProfileName);
1470 return RTEXITCODE_FAILURE;
1471 }
1472
1473 /* Second step*/
1474 RTPrintf(Cloud::tr("Second, refresh information about cloud instance ...\n"));
1475 ComPtr<ICloudMachine> pMachine;
1476 CHECK_ERROR2_RET(hrc, oCloudClient,
1477 GetCloudMachine(bstrFoundMachineVBoxId.raw(), pMachine.asOutParam()), RTEXITCODE_FAILURE);
1478
1479 ComPtr<IProgress> pRefreshProgress;
1480 CHECK_ERROR2_RET(hrc, pMachine, Refresh(pRefreshProgress.asOutParam()), RTEXITCODE_FAILURE);
1481
1482 hrc = showProgress(pRefreshProgress);
1483 CHECK_PROGRESS_ERROR_RET(pRefreshProgress, (Cloud::tr("Refreshing information about cloud instance failed")), RTEXITCODE_FAILURE);
1484
1485 /* Third step*/
1486 RTPrintf(Cloud::tr("Third, request metric data from cloud instance ...\n"));
1487 ComPtr<IProgress> progress2;
1488 ComPtr<IStringArray> returnDataValues;
1489 ComPtr<IStringArray> returnDataTimestamps;
1490 ComPtr<IStringArray> returnMeasureUnits;
1491
1492 CHECK_ERROR2_RET(hrc, pMachine, EnumerateMetricData(aMetricType,
1493 metricPoins,
1494 returnDataValues.asOutParam(),
1495 returnDataTimestamps.asOutParam(),
1496 returnMeasureUnits.asOutParam(),
1497 progress2.asOutParam()), RTEXITCODE_FAILURE);
1498
1499 hrc = showProgress(progress2);
1500 CHECK_PROGRESS_ERROR_RET(progress2, (Cloud::tr("Getting metric data failed")), RTEXITCODE_FAILURE);
1501
1502 com::SafeArray<BSTR> dataValueArray;
1503 CHECK_ERROR2_RET(hrc,
1504 returnDataValues, COMGETTER(Values)(ComSafeArrayAsOutParam(dataValueArray)),
1505 RTEXITCODE_FAILURE);
1506
1507 com::SafeArray<BSTR> dataTimestampArray;
1508 CHECK_ERROR2_RET(hrc,
1509 returnDataTimestamps, COMGETTER(Values)(ComSafeArrayAsOutParam(dataTimestampArray)),
1510 RTEXITCODE_FAILURE);
1511
1512 com::SafeArray<BSTR> measureUnitArray;
1513 CHECK_ERROR2_RET(hrc,
1514 returnMeasureUnits, COMGETTER(Values)(ComSafeArrayAsOutParam(measureUnitArray)),
1515 RTEXITCODE_FAILURE);
1516
1517 size_t cDataValueArraySize = dataValueArray.size();
1518 Bstr unit = cDataValueArraySize == 0 ? Bstr("unknown units") : measureUnitArray[0];
1519 RTPrintf(Cloud::tr("The %s metric values (in %ls):\n"), strMetricName.c_str(), unit.raw());
1520
1521 if (cDataValueArraySize == 0)
1522 RTPrintf(Cloud::tr("\tThe list of metric data is empty. It may mean that an appropriate service wasn't run on the instance.\n"));
1523 else
1524 {
1525 Bstr value;
1526 for (size_t k = 0; k < cDataValueArraySize; ++k)
1527 {
1528 value = dataValueArray[k];
1529 Utf8Str strTimestamp(dataTimestampArray[k]);
1530 RTPrintf(Cloud::tr("%d: %s[%s] = %ls\n"), k, strMetricName.c_str(), strTimestamp.c_str(), value.raw());
1531 }
1532 }
1533
1534 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1535}
1536
1537
[78734]1538static RTEXITCODE startCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1539{
1540 HRESULT hrc = S_OK;
1541
1542 static const RTGETOPTDEF s_aOptions[] =
1543 {
[83279]1544 { "--id", 'i', RTGETOPT_REQ_STRING },
[93872]1545 { "help", 'h', RTGETOPT_REQ_NOTHING },
1546 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[78734]1547 };
1548 RTGETOPTSTATE GetState;
1549 RTGETOPTUNION ValueUnion;
1550 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1551 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]1552 if (a->argc == iFirst)
1553 {
[92372]1554 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]1555 printHelp(g_pStdOut);
1556 return RTEXITCODE_SUCCESS;
1557 }
[78734]1558
1559 Utf8Str strInstanceId;
[79980]1560
[78734]1561 int c;
1562 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1563 {
1564 switch (c)
1565 {
1566 case 'i':
[79980]1567 {
1568 if (strInstanceId.isNotEmpty())
[92372]1569 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
[79980]1570
1571 strInstanceId = ValueUnion.psz;
1572 if (strInstanceId.isEmpty())
[92372]1573 return errorArgument(Cloud::tr("Empty parameter: --id"));
[79980]1574
[78734]1575 break;
[79980]1576 }
[93872]1577 case 'h':
[83279]1578 printHelp(g_pStdOut);
1579 return RTEXITCODE_SUCCESS;
[78734]1580 case VINF_GETOPT_NOT_OPTION:
1581 return errorUnknownSubcommand(ValueUnion.psz);
[79980]1582
[78734]1583 default:
1584 return errorGetOpt(c, &ValueUnion);
1585 }
1586 }
1587
[83279]1588 /* Delayed check. It allows us to print help information.*/
1589 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1590 if (FAILED(hrc))
1591 return RTEXITCODE_FAILURE;
1592
[79980]1593 if (strInstanceId.isEmpty())
[92372]1594 return errorArgument(Cloud::tr("Missing parameter: --id"));
[79980]1595
[78734]1596 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1597
1598 ComObjPtr<ICloudClient> oCloudClient;
1599 CHECK_ERROR2_RET(hrc, pCloudProfile,
1600 CreateCloudClient(oCloudClient.asOutParam()),
1601 RTEXITCODE_FAILURE);
[92372]1602 RTPrintf(Cloud::tr("Starting cloud instance with id %s...\n"), strInstanceId.c_str());
[78734]1603
1604 ComPtr<IProgress> progress;
1605 CHECK_ERROR2_RET(hrc, oCloudClient,
[79943]1606 StartInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
[78734]1607 RTEXITCODE_FAILURE);
1608 hrc = showProgress(progress);
[92372]1609 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Starting the cloud instance failed")), RTEXITCODE_FAILURE);
[78734]1610
1611 if (SUCCEEDED(hrc))
[92372]1612 RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was started\n"),
[78734]1613 strInstanceId.c_str(),
1614 pCommonOpts->provider.pszProviderName,
1615 pCommonOpts->profile.pszProfileName);
1616
1617 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1618}
1619
1620static RTEXITCODE pauseCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1621{
1622 HRESULT hrc = S_OK;
1623
1624 static const RTGETOPTDEF s_aOptions[] =
1625 {
[83279]1626 { "--id", 'i', RTGETOPT_REQ_STRING },
[93872]1627 { "help", 'h', RTGETOPT_REQ_NOTHING },
1628 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[78734]1629 };
1630 RTGETOPTSTATE GetState;
1631 RTGETOPTUNION ValueUnion;
1632 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1633 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]1634 if (a->argc == iFirst)
1635 {
[92372]1636 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]1637 printHelp(g_pStdOut);
1638 return RTEXITCODE_SUCCESS;
1639 }
[78734]1640
1641 Utf8Str strInstanceId;
[79980]1642
[78734]1643 int c;
1644 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1645 {
1646 switch (c)
1647 {
1648 case 'i':
[79980]1649 {
1650 if (strInstanceId.isNotEmpty())
[92372]1651 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
[79980]1652
1653 strInstanceId = ValueUnion.psz;
1654 if (strInstanceId.isEmpty())
[92372]1655 return errorArgument(Cloud::tr("Empty parameter: --id"));
[79980]1656
[78734]1657 break;
[79980]1658 }
[93872]1659 case 'h':
[83279]1660 printHelp(g_pStdOut);
1661 return RTEXITCODE_SUCCESS;
[78734]1662 case VINF_GETOPT_NOT_OPTION:
1663 return errorUnknownSubcommand(ValueUnion.psz);
[79980]1664
[78734]1665 default:
1666 return errorGetOpt(c, &ValueUnion);
1667 }
1668 }
1669
[83279]1670 /* Delayed check. It allows us to print help information.*/
1671 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1672 if (FAILED(hrc))
1673 return RTEXITCODE_FAILURE;
1674
[79980]1675 if (strInstanceId.isEmpty())
[92372]1676 return errorArgument(Cloud::tr("Missing parameter: --id"));
[79980]1677
[78734]1678 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1679
1680 ComObjPtr<ICloudClient> oCloudClient;
1681 CHECK_ERROR2_RET(hrc, pCloudProfile,
1682 CreateCloudClient(oCloudClient.asOutParam()),
1683 RTEXITCODE_FAILURE);
[92372]1684 RTPrintf(Cloud::tr("Pausing cloud instance with id %s...\n"), strInstanceId.c_str());
[78734]1685
1686 ComPtr<IProgress> progress;
1687 CHECK_ERROR2_RET(hrc, oCloudClient,
[79943]1688 PauseInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
[78734]1689 RTEXITCODE_FAILURE);
1690 hrc = showProgress(progress);
[92372]1691 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Pause the cloud instance failed")), RTEXITCODE_FAILURE);
[78734]1692
1693 if (SUCCEEDED(hrc))
[92372]1694 RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was paused\n"),
[78734]1695 strInstanceId.c_str(),
1696 pCommonOpts->provider.pszProviderName,
1697 pCommonOpts->profile.pszProfileName);
1698
1699 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1700}
1701
1702static RTEXITCODE terminateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1703{
1704 HRESULT hrc = S_OK;
1705
1706 static const RTGETOPTDEF s_aOptions[] =
1707 {
[83279]1708 { "--id", 'i', RTGETOPT_REQ_STRING },
[93872]1709 { "help", 'h', RTGETOPT_REQ_NOTHING },
1710 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[78734]1711 };
1712 RTGETOPTSTATE GetState;
1713 RTGETOPTUNION ValueUnion;
1714 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1715 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]1716 if (a->argc == iFirst)
1717 {
[92372]1718 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]1719 printHelp(g_pStdOut);
1720 return RTEXITCODE_SUCCESS;
1721 }
[78734]1722
1723 Utf8Str strInstanceId;
[79980]1724
[78734]1725 int c;
1726 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1727 {
1728 switch (c)
1729 {
1730 case 'i':
[79980]1731 {
1732 if (strInstanceId.isNotEmpty())
[92372]1733 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
[79980]1734
1735 strInstanceId = ValueUnion.psz;
1736 if (strInstanceId.isEmpty())
[92372]1737 return errorArgument(Cloud::tr("Empty parameter: --id"));
[79980]1738
[78734]1739 break;
[79980]1740 }
[93872]1741 case 'h':
[83279]1742 printHelp(g_pStdOut);
1743 return RTEXITCODE_SUCCESS;
[78734]1744 case VINF_GETOPT_NOT_OPTION:
1745 return errorUnknownSubcommand(ValueUnion.psz);
[79980]1746
[78734]1747 default:
1748 return errorGetOpt(c, &ValueUnion);
1749 }
1750 }
1751
[83279]1752 /* Delayed check. It allows us to print help information.*/
1753 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1754 if (FAILED(hrc))
1755 return RTEXITCODE_FAILURE;
1756
[79980]1757 if (strInstanceId.isEmpty())
[92372]1758 return errorArgument(Cloud::tr("Missing parameter: --id"));
[79980]1759
1760
[78734]1761 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1762
1763 ComObjPtr<ICloudClient> oCloudClient;
1764 CHECK_ERROR2_RET(hrc, pCloudProfile,
1765 CreateCloudClient(oCloudClient.asOutParam()),
1766 RTEXITCODE_FAILURE);
[92372]1767 RTPrintf(Cloud::tr("Terminating cloud instance with id %s...\n"), strInstanceId.c_str());
[78734]1768
1769 ComPtr<IProgress> progress;
1770 CHECK_ERROR2_RET(hrc, oCloudClient,
[79943]1771 TerminateInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
[78734]1772 RTEXITCODE_FAILURE);
1773 hrc = showProgress(progress);
[92372]1774 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Termination the cloud instance failed")), RTEXITCODE_FAILURE);
[78734]1775
1776 if (SUCCEEDED(hrc))
[92372]1777 RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was terminated\n"),
[78734]1778 strInstanceId.c_str(),
1779 pCommonOpts->provider.pszProviderName,
1780 pCommonOpts->profile.pszProfileName);
1781
1782 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1783}
1784
[98701]1785static RTEXITCODE resetCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1786{
1787 HRESULT hrc = S_OK;
1788
1789 static const RTGETOPTDEF s_aOptions[] =
1790 {
1791 { "--id", 'i', RTGETOPT_REQ_STRING },
1792 { "help", 'h', RTGETOPT_REQ_NOTHING },
1793 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1794 };
1795 RTGETOPTSTATE GetState;
1796 RTGETOPTUNION ValueUnion;
1797 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1798 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1799 if (a->argc == iFirst)
1800 {
1801 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1802 printHelp(g_pStdOut);
1803 return RTEXITCODE_SUCCESS;
1804 }
1805
1806 Utf8Str strInstanceId;
1807
1808 int c;
1809 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1810 {
1811 switch (c)
1812 {
1813 case 'i':
1814 {
1815 if (strInstanceId.isNotEmpty())
1816 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
1817
1818 strInstanceId = ValueUnion.psz;
1819 if (strInstanceId.isEmpty())
1820 return errorArgument(Cloud::tr("Empty parameter: --id"));
1821
1822 break;
1823 }
1824 case 'h':
1825 printHelp(g_pStdOut);
1826 return RTEXITCODE_SUCCESS;
1827 case VINF_GETOPT_NOT_OPTION:
1828 return errorUnknownSubcommand(ValueUnion.psz);
1829
1830 default:
1831 return errorGetOpt(c, &ValueUnion);
1832 }
1833 }
1834
1835 /* Delayed check. It allows us to print help information.*/
1836 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1837 if (FAILED(hrc))
1838 return RTEXITCODE_FAILURE;
1839
1840 if (strInstanceId.isEmpty())
1841 return errorArgument(Cloud::tr("Missing parameter: --id"));
1842
1843 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1844
1845 ComObjPtr<ICloudClient> oCloudClient;
1846 CHECK_ERROR2_RET(hrc, pCloudProfile,
1847 CreateCloudClient(oCloudClient.asOutParam()),
1848 RTEXITCODE_FAILURE);
1849 RTPrintf(Cloud::tr("Reset cloud instance with id %s...\n"), strInstanceId.c_str());
1850
1851 ComPtr<IProgress> progress;
1852 CHECK_ERROR2_RET(hrc, oCloudClient,
1853 ResetInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
1854 RTEXITCODE_FAILURE);
1855 hrc = showProgress(progress);
1856 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Reset the cloud instance failed")), RTEXITCODE_FAILURE);
1857
1858 if (SUCCEEDED(hrc))
1859 RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was reset\n"),
1860 strInstanceId.c_str(),
1861 pCommonOpts->provider.pszProviderName,
1862 pCommonOpts->profile.pszProfileName);
1863
1864 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1865}
1866
[78734]1867static RTEXITCODE handleCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1868{
[91133]1869 enum
1870 {
1871 kCloudInstanceIota = 1000,
1872 kCloudInstance_Create,
1873 kCloudInstance_Info,
1874 kCloudInstance_Pause,
1875 kCloudInstance_Start,
1876 kCloudInstance_Terminate,
1877 kCloudInstance_Update,
[98701]1878 kCloudInstance_Reset,
[100808]1879 kCloudInstance_Clone,
[102095]1880 kCloudInstance_MetricList,
1881 kCloudInstance_MetricData,
[91133]1882 };
1883
1884 static const RTGETOPTDEF s_aOptions[] =
1885 {
1886 { "create", kCloudInstance_Create, RTGETOPT_REQ_NOTHING },
1887 { "info", kCloudInstance_Info, RTGETOPT_REQ_NOTHING },
1888 { "pause", kCloudInstance_Pause, RTGETOPT_REQ_NOTHING },
1889 { "start", kCloudInstance_Start, RTGETOPT_REQ_NOTHING },
1890 { "terminate", kCloudInstance_Terminate, RTGETOPT_REQ_NOTHING },
1891 { "update", kCloudInstance_Update, RTGETOPT_REQ_NOTHING },
[98701]1892 { "reset", kCloudInstance_Reset, RTGETOPT_REQ_NOTHING },
[100808]1893 { "clone", kCloudInstance_Clone, RTGETOPT_REQ_NOTHING },
[102095]1894 { "metriclist", kCloudInstance_MetricList,RTGETOPT_REQ_NOTHING },
1895 { "metricdata", kCloudInstance_MetricData,RTGETOPT_REQ_NOTHING },
[91133]1896
1897 { "help", 'h', RTGETOPT_REQ_NOTHING },
1898 { "-?", 'h', RTGETOPT_REQ_NOTHING },
1899 { "-help", 'h', RTGETOPT_REQ_NOTHING },
1900 { "--help", 'h', RTGETOPT_REQ_NOTHING },
1901 };
1902
[83279]1903 if (a->argc == iFirst)
1904 {
[92372]1905 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]1906 printHelp(g_pStdOut);
1907 return RTEXITCODE_SUCCESS;
1908 }
[78734]1909
1910 RTGETOPTSTATE GetState;
1911 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1912 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1913
1914 int c;
1915 RTGETOPTUNION ValueUnion;
1916 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1917 {
1918 switch (c)
1919 {
1920 /* Sub-commands: */
[91133]1921 case kCloudInstance_Create:
[99513]1922 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_CREATE);
[78734]1923 return createCloudInstance(a, GetState.iNext, pCommonOpts);
[91133]1924
1925 case kCloudInstance_Start:
[99513]1926 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_START);
[78734]1927 return startCloudInstance(a, GetState.iNext, pCommonOpts);
[91133]1928
1929 case kCloudInstance_Pause:
[99513]1930 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_PAUSE);
[78734]1931 return pauseCloudInstance(a, GetState.iNext, pCommonOpts);
[91133]1932
1933 case kCloudInstance_Info:
[99513]1934 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_INFO);
[78734]1935 return showCloudInstanceInfo(a, GetState.iNext, pCommonOpts);
[91133]1936
1937 case kCloudInstance_Update:
[99513]1938// setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_UPDATE);
[78734]1939 return updateCloudInstance(a, GetState.iNext, pCommonOpts);
[91133]1940
1941 case kCloudInstance_Terminate:
[99513]1942 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_TERMINATE);
[78734]1943 return terminateCloudInstance(a, GetState.iNext, pCommonOpts);
[91133]1944
[98701]1945 case kCloudInstance_Reset:
[99513]1946 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_RESET);
[98701]1947 return resetCloudInstance(a, GetState.iNext, pCommonOpts);
1948
[100808]1949 case kCloudInstance_Clone:
[100809]1950 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_CLONE);
[100808]1951 return cloneCloudInstance(a, GetState.iNext, pCommonOpts);
1952
[102095]1953 case kCloudInstance_MetricData:
1954 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_METRICDATA);
1955 return cloudInstanceMetricData(a, GetState.iNext, pCommonOpts);
1956
1957 case kCloudInstance_MetricList:
1958 setCurrentSubcommand(HELP_SCOPE_CLOUD_INSTANCE_METRICLIST);
1959 return cloudInstanceMetricList(a, GetState.iNext, pCommonOpts);
1960
[91133]1961 case 'h':
[83279]1962 printHelp(g_pStdOut);
1963 return RTEXITCODE_SUCCESS;
[91133]1964
[78734]1965 case VINF_GETOPT_NOT_OPTION:
1966 return errorUnknownSubcommand(ValueUnion.psz);
1967
1968 default:
1969 return errorGetOpt(c, &ValueUnion);
1970 }
1971 }
1972
1973 return errorNoSubcommand();
1974}
1975
[79319]1976
1977static RTEXITCODE createCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1978{
1979 HRESULT hrc = S_OK;
1980
1981 static const RTGETOPTDEF s_aOptions[] =
1982 {
[80743]1983 { "--object-name", 'o', RTGETOPT_REQ_STRING },
1984 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
[79319]1985 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
1986 { "--instance-id", 'i', RTGETOPT_REQ_STRING },
[80743]1987 { "--display-name", 'd', RTGETOPT_REQ_STRING },
1988 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
[93872]1989 { "help", 'h', RTGETOPT_REQ_NOTHING },
1990 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[79319]1991 };
1992 RTGETOPTSTATE GetState;
1993 RTGETOPTUNION ValueUnion;
1994 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1995 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]1996 if (a->argc == iFirst)
1997 {
[92372]1998 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]1999 printHelp(g_pStdOut);
2000 return RTEXITCODE_SUCCESS;
2001 }
[79319]2002
[79583]2003 Utf8Str strCompartmentId;
2004 Utf8Str strInstanceId;
2005 Utf8Str strDisplayName;
[80743]2006 Utf8Str strBucketName;
2007 Utf8Str strObjectName;
[79319]2008 com::SafeArray<BSTR> parameters;
2009
2010 int c;
2011 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2012 {
2013 switch (c)
2014 {
2015 case 'c':
[79583]2016 strCompartmentId=ValueUnion.psz;
2017 Bstr(Utf8Str("compartment-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
[79319]2018 break;
2019 case 'i':
[79583]2020 strInstanceId=ValueUnion.psz;
2021 Bstr(Utf8Str("instance-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
[79319]2022 break;
2023 case 'd':
[79583]2024 strDisplayName=ValueUnion.psz;
2025 Bstr(Utf8Str("display-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
[79319]2026 break;
[80743]2027 case 'o':
2028 strObjectName=ValueUnion.psz;
2029 Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
2030 break;
2031 case 'b':
2032 strBucketName=ValueUnion.psz;
2033 Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
2034 break;
2035 case 'm':
2036 strBucketName=ValueUnion.psz;
2037 Bstr(Utf8Str("launch-mode=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
2038 break;
[93872]2039 case 'h':
[83279]2040 printHelp(g_pStdOut);
2041 return RTEXITCODE_SUCCESS;
[79319]2042 case VINF_GETOPT_NOT_OPTION:
2043 return errorUnknownSubcommand(ValueUnion.psz);
2044 default:
2045 return errorGetOpt(c, &ValueUnion);
2046 }
2047 }
2048
[83279]2049 /* Delayed check. It allows us to print help information.*/
2050 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2051 if (FAILED(hrc))
2052 return RTEXITCODE_FAILURE;
2053
[80743]2054 if (strInstanceId.isNotEmpty() && strObjectName.isNotEmpty())
[92372]2055 return errorArgument(Cloud::tr("Conflicting parameters: --instance-id and --object-name can't be used together. Choose one."));
[80743]2056
[79319]2057 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
2058
2059 ComObjPtr<ICloudClient> oCloudClient;
2060 CHECK_ERROR2_RET(hrc, pCloudProfile,
2061 CreateCloudClient(oCloudClient.asOutParam()),
2062 RTEXITCODE_FAILURE);
[80743]2063 if (strInstanceId.isNotEmpty())
[92372]2064 RTPrintf(Cloud::tr("Creating cloud image with name \'%s\' from the instance \'%s\'...\n"),
[80743]2065 strDisplayName.c_str(), strInstanceId.c_str());
2066 else
[92372]2067 RTPrintf(Cloud::tr("Creating cloud image with name \'%s\' from the object \'%s\' in the bucket \'%s\'...\n"),
[80743]2068 strDisplayName.c_str(), strObjectName.c_str(), strBucketName.c_str());
[79319]2069
2070 ComPtr<IProgress> progress;
2071 CHECK_ERROR2_RET(hrc, oCloudClient,
2072 CreateImage(ComSafeArrayAsInParam(parameters), progress.asOutParam()),
2073 RTEXITCODE_FAILURE);
2074 hrc = showProgress(progress);
[92372]2075 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Creating cloud image failed")), RTEXITCODE_FAILURE);
[79319]2076
2077 if (SUCCEEDED(hrc))
[92372]2078 RTPrintf(Cloud::tr("Cloud image was created successfully\n"));
[79319]2079
2080 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2081}
2082
2083
2084static RTEXITCODE exportCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2085{
2086 HRESULT hrc = S_OK;
2087
2088 static const RTGETOPTDEF s_aOptions[] =
2089 {
[80739]2090 { "--id", 'i', RTGETOPT_REQ_STRING },
[79319]2091 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
2092 { "--object-name", 'o', RTGETOPT_REQ_STRING },
[80739]2093 { "--display-name", 'd', RTGETOPT_REQ_STRING },
2094 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
[93872]2095 { "help", 'h', RTGETOPT_REQ_NOTHING },
2096 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[79319]2097 };
2098 RTGETOPTSTATE GetState;
2099 RTGETOPTUNION ValueUnion;
2100 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2101 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]2102 if (a->argc == iFirst)
2103 {
[92372]2104 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]2105 printHelp(g_pStdOut);
2106 return RTEXITCODE_SUCCESS;
2107 }
[79319]2108
[80739]2109 Utf8Str strImageId; /* XXX: this is vbox "image", i.e. medium */
[79583]2110 Utf8Str strBucketName;
2111 Utf8Str strObjectName;
[80739]2112 Utf8Str strDisplayName;
2113 Utf8Str strLaunchMode;
[79935]2114 com::SafeArray<BSTR> parameters;
[79319]2115
2116 int c;
2117 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2118 {
2119 switch (c)
2120 {
[80739]2121 case 'b': /* --bucket-name */
[79935]2122 {
2123 if (strBucketName.isNotEmpty())
[92372]2124 return errorArgument(Cloud::tr("Duplicate parameter: --bucket-name"));
[79935]2125
2126 strBucketName = ValueUnion.psz;
2127 if (strBucketName.isEmpty())
[92372]2128 return errorArgument(Cloud::tr("Empty parameter: --bucket-name"));
[79935]2129
[79319]2130 break;
[79935]2131 }
2132
[80739]2133 case 'o': /* --object-name */
[79935]2134 {
2135 if (strObjectName.isNotEmpty())
[92372]2136 return errorArgument(Cloud::tr("Duplicate parameter: --object-name"));
[79935]2137
2138 strObjectName = ValueUnion.psz;
2139 if (strObjectName.isEmpty())
[92372]2140 return errorArgument(Cloud::tr("Empty parameter: --object-name"));
[79935]2141
[79319]2142 break;
[79935]2143 }
2144
[80739]2145 case 'i': /* --id */
[79935]2146 {
2147 if (strImageId.isNotEmpty())
[92372]2148 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
[79935]2149
2150 strImageId = ValueUnion.psz;
2151 if (strImageId.isEmpty())
[92372]2152 return errorArgument(Cloud::tr("Empty parameter: --id"));
[79935]2153
[79319]2154 break;
[79935]2155 }
2156
[80739]2157 case 'd': /* --display-name */
2158 {
2159 if (strDisplayName.isNotEmpty())
[92372]2160 return errorArgument(Cloud::tr("Duplicate parameter: --display-name"));
[80739]2161
2162 strDisplayName = ValueUnion.psz;
2163 if (strDisplayName.isEmpty())
[92372]2164 return errorArgument(Cloud::tr("Empty parameter: --display-name"));
[80739]2165
2166 break;
2167 }
2168
2169 case 'm': /* --launch-mode */
2170 {
2171 if (strLaunchMode.isNotEmpty())
[92372]2172 return errorArgument(Cloud::tr("Duplicate parameter: --launch-mode"));
[80739]2173
2174 strLaunchMode = ValueUnion.psz;
2175 if (strLaunchMode.isEmpty())
[92372]2176 return errorArgument(Cloud::tr("Empty parameter: --launch-mode"));
[80739]2177
2178 break;
2179 }
2180
[93872]2181 case 'h':
[83279]2182 printHelp(g_pStdOut);
2183 return RTEXITCODE_SUCCESS;
2184
[79319]2185 case VINF_GETOPT_NOT_OPTION:
2186 return errorUnknownSubcommand(ValueUnion.psz);
[79935]2187
[79319]2188 default:
2189 return errorGetOpt(c, &ValueUnion);
2190 }
2191 }
2192
[83279]2193 /* Delayed check. It allows us to print help information.*/
2194 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2195 if (FAILED(hrc))
2196 return RTEXITCODE_FAILURE;
2197
[80739]2198 if (strImageId.isNotEmpty())
2199 BstrFmt("image-id=%s", strImageId.c_str()).detachTo(parameters.appendedRaw());
2200 else
[92372]2201 return errorArgument(Cloud::tr("Missing parameter: --id"));
[80739]2202
[79935]2203 if (strBucketName.isNotEmpty())
2204 BstrFmt("bucket-name=%s", strBucketName.c_str()).detachTo(parameters.appendedRaw());
2205 else
[92372]2206 return errorArgument(Cloud::tr("Missing parameter: --bucket-name"));
[79935]2207
2208 if (strObjectName.isNotEmpty())
2209 BstrFmt("object-name=%s", strObjectName.c_str()).detachTo(parameters.appendedRaw());
2210
[80739]2211 if (strDisplayName.isNotEmpty())
2212 BstrFmt("display-name=%s", strDisplayName.c_str()).detachTo(parameters.appendedRaw());
[79935]2213
[80739]2214 if (strLaunchMode.isNotEmpty())
2215 BstrFmt("launch-mode=%s", strLaunchMode.c_str()).detachTo(parameters.appendedRaw());
[79935]2216
[80739]2217
[79319]2218 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
2219
2220 ComObjPtr<ICloudClient> oCloudClient;
2221 CHECK_ERROR2_RET(hrc, pCloudProfile,
2222 CreateCloudClient(oCloudClient.asOutParam()),
2223 RTEXITCODE_FAILURE);
2224
[79935]2225 if (strObjectName.isNotEmpty())
[92372]2226 RTPrintf(Cloud::tr("Exporting image \'%s\' to the Cloud with name \'%s\'...\n"),
[79935]2227 strImageId.c_str(), strObjectName.c_str());
2228 else
[92372]2229 RTPrintf(Cloud::tr("Exporting image \'%s\' to the Cloud with default name\n"),
[79935]2230 strImageId.c_str());
2231
[79583]2232 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2233 SafeIfaceArray<IMedium> aImageList;
2234 CHECK_ERROR2_RET(hrc, pVirtualBox,
2235 COMGETTER(HardDisks)(ComSafeArrayAsOutParam(aImageList)),
2236 RTEXITCODE_FAILURE);
2237
2238 ComPtr<IMedium> pImage;
2239 size_t cImages = aImageList.size();
2240 bool fFound = false;
2241 for (size_t i = 0; i < cImages; ++i)
2242 {
2243 pImage = aImageList[i];
2244 Bstr bstrImageId;
2245 hrc = pImage->COMGETTER(Id)(bstrImageId.asOutParam());
2246 if (FAILED(hrc))
2247 continue;
2248
2249 com::Guid imageId(bstrImageId);
2250
2251 if (!imageId.isValid() || imageId.isZero())
2252 continue;
2253
2254 if (!strImageId.compare(imageId.toString()))
2255 {
2256 fFound = true;
[92372]2257 RTPrintf(Cloud::tr("Image %s was found\n"), strImageId.c_str());
[79583]2258 break;
2259 }
2260 }
2261
2262 if (!fFound)
2263 {
[92372]2264 RTPrintf(Cloud::tr("Process of exporting the image to the Cloud was interrupted. The image wasn't found.\n"));
[79583]2265 return RTEXITCODE_FAILURE;
2266 }
2267
[79319]2268 ComPtr<IProgress> progress;
2269 CHECK_ERROR2_RET(hrc, oCloudClient,
[81119]2270 ExportImage(pImage, ComSafeArrayAsInParam(parameters), progress.asOutParam()),
[79319]2271 RTEXITCODE_FAILURE);
2272 hrc = showProgress(progress);
[92372]2273 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Export the image to the Cloud failed")), RTEXITCODE_FAILURE);
[79319]2274
2275 if (SUCCEEDED(hrc))
[92372]2276 RTPrintf(Cloud::tr("Export the image to the Cloud was successfull\n"));
[79319]2277
2278 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2279}
2280
2281static RTEXITCODE importCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2282{
2283 HRESULT hrc = S_OK;
2284
2285 static const RTGETOPTDEF s_aOptions[] =
2286 {
[79727]2287 { "--id", 'i', RTGETOPT_REQ_STRING },
[79319]2288 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
[83279]2289 { "--object-name", 'o', RTGETOPT_REQ_STRING },
[93872]2290 { "help", 'h', RTGETOPT_REQ_NOTHING },
2291 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[79319]2292 };
2293 RTGETOPTSTATE GetState;
2294 RTGETOPTUNION ValueUnion;
2295 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2296 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]2297 if (a->argc == iFirst)
2298 {
[92372]2299 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]2300 printHelp(g_pStdOut);
2301 return RTEXITCODE_SUCCESS;
2302 }
[79319]2303
[79605]2304 Utf8Str strImageId;
[79583]2305 Utf8Str strCompartmentId;
2306 Utf8Str strBucketName;
2307 Utf8Str strObjectName;
2308 Utf8Str strDisplayName;
[79319]2309 com::SafeArray<BSTR> parameters;
2310
2311 int c;
2312 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2313 {
2314 switch (c)
2315 {
[79605]2316 case 'i':
2317 strImageId=ValueUnion.psz;
[79319]2318 break;
2319 case 'b':
[79583]2320 strBucketName=ValueUnion.psz;
2321 Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
[79319]2322 break;
2323 case 'o':
[79583]2324 strObjectName=ValueUnion.psz;
2325 Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
[79319]2326 break;
[93872]2327 case 'h':
[83279]2328 printHelp(g_pStdOut);
2329 return RTEXITCODE_SUCCESS;
[79319]2330 case VINF_GETOPT_NOT_OPTION:
2331 return errorUnknownSubcommand(ValueUnion.psz);
2332 default:
2333 return errorGetOpt(c, &ValueUnion);
2334 }
2335 }
2336
[83279]2337 /* Delayed check. It allows us to print help information.*/
2338 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2339 if (FAILED(hrc))
2340 return RTEXITCODE_FAILURE;
2341
[79319]2342 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
2343
[79605]2344 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
[79319]2345 ComObjPtr<ICloudClient> oCloudClient;
2346 CHECK_ERROR2_RET(hrc, pCloudProfile,
2347 CreateCloudClient(oCloudClient.asOutParam()),
2348 RTEXITCODE_FAILURE);
[92372]2349 RTPrintf(Cloud::tr("Creating an object \'%s\' from the cloud image \'%s\'...\n"), strObjectName.c_str(), strImageId.c_str());
[79319]2350
2351 ComPtr<IProgress> progress;
2352 CHECK_ERROR2_RET(hrc, oCloudClient,
[81119]2353 ImportImage(Bstr(strImageId).raw(), ComSafeArrayAsInParam(parameters), progress.asOutParam()),
[79319]2354 RTEXITCODE_FAILURE);
2355 hrc = showProgress(progress);
[92372]2356 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Cloud image import failed")), RTEXITCODE_FAILURE);
[79319]2357
2358 if (SUCCEEDED(hrc))
[79605]2359 {
[92372]2360 RTPrintf(Cloud::tr("Cloud image was imported successfully. Find the downloaded object with the name %s "
2361 "in the system temp folder (find the possible environment variables like TEMP, TMP and etc.)\n"),
[79605]2362 strObjectName.c_str());
2363 }
[79319]2364
2365 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2366}
2367
2368static RTEXITCODE showCloudImageInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2369{
2370 HRESULT hrc = S_OK;
2371
2372 static const RTGETOPTDEF s_aOptions[] =
2373 {
[83279]2374 { "--id", 'i', RTGETOPT_REQ_STRING },
[93872]2375 { "help", 'h', RTGETOPT_REQ_NOTHING },
2376 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[79319]2377 };
2378 RTGETOPTSTATE GetState;
2379 RTGETOPTUNION ValueUnion;
2380 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2381 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]2382 if (a->argc == iFirst)
2383 {
[92372]2384 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]2385 printHelp(g_pStdOut);
2386 return RTEXITCODE_SUCCESS;
2387 }
[79319]2388
2389 Utf8Str strImageId;
2390
2391 int c;
2392 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2393 {
2394 switch (c)
2395 {
2396 case 'i':
2397 strImageId = ValueUnion.psz;
2398 break;
[93872]2399 case 'h':
[83279]2400 printHelp(g_pStdOut);
2401 return RTEXITCODE_SUCCESS;
[79319]2402 case VINF_GETOPT_NOT_OPTION:
2403 return errorUnknownSubcommand(ValueUnion.psz);
2404 default:
2405 return errorGetOpt(c, &ValueUnion);
2406 }
2407 }
2408
[83279]2409 /* Delayed check. It allows us to print help information.*/
2410 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2411 if (FAILED(hrc))
2412 return RTEXITCODE_FAILURE;
2413
[79319]2414 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
2415
2416 ComObjPtr<ICloudClient> oCloudClient;
2417 CHECK_ERROR2_RET(hrc, pCloudProfile,
2418 CreateCloudClient(oCloudClient.asOutParam()),
2419 RTEXITCODE_FAILURE);
[92372]2420 RTPrintf(Cloud::tr("Getting information about the cloud image with id \'%s\'...\n"), strImageId.c_str());
[79319]2421
2422 ComPtr<IStringArray> infoArray;
2423 com::SafeArray<BSTR> pStrInfoArray;
2424 ComPtr<IProgress> pProgress;
2425
[92372]2426 RTPrintf(Cloud::tr("Reply is in the form \'image property\' = \'value\'\n"));
[79319]2427 CHECK_ERROR2_RET(hrc, oCloudClient,
[79943]2428 GetImageInfo(Bstr(strImageId).raw(),
[79319]2429 infoArray.asOutParam(),
2430 pProgress.asOutParam()),
2431 RTEXITCODE_FAILURE);
2432
2433 hrc = showProgress(pProgress);
[92372]2434 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Getting information about the cloud image failed")), RTEXITCODE_FAILURE);
[79319]2435
2436 CHECK_ERROR2_RET(hrc,
2437 infoArray, COMGETTER(Values)(ComSafeArrayAsOutParam(pStrInfoArray)),
2438 RTEXITCODE_FAILURE);
2439
[92372]2440 RTPrintf(Cloud::tr("General information about the image:\n"));
[79319]2441 size_t cParamNames = pStrInfoArray.size();
2442 for (size_t k = 0; k < cParamNames; k++)
2443 {
2444 Utf8Str data(pStrInfoArray[k]);
2445 RTPrintf("\t%s\n", data.c_str());
2446 }
2447
2448 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2449}
2450
2451static RTEXITCODE updateCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2452{
2453 RT_NOREF(a);
2454 RT_NOREF(iFirst);
2455 RT_NOREF(pCommonOpts);
2456 return RTEXITCODE_SUCCESS;
2457}
2458
2459static RTEXITCODE deleteCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2460{
2461 HRESULT hrc = S_OK;
2462
2463 static const RTGETOPTDEF s_aOptions[] =
2464 {
[83279]2465 { "--id", 'i', RTGETOPT_REQ_STRING },
[93872]2466 { "help", 'h', RTGETOPT_REQ_NOTHING },
2467 { "--help", 'h', RTGETOPT_REQ_NOTHING }
[79319]2468 };
2469 RTGETOPTSTATE GetState;
2470 RTGETOPTUNION ValueUnion;
2471 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2472 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
[83279]2473 if (a->argc == iFirst)
2474 {
[92372]2475 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]2476 printHelp(g_pStdOut);
2477 return RTEXITCODE_SUCCESS;
2478 }
[79319]2479
2480 Utf8Str strImageId;
2481
2482 int c;
2483 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2484 {
2485 switch (c)
2486 {
2487 case 'i':
[79942]2488 {
2489 if (strImageId.isNotEmpty())
[92372]2490 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
[79942]2491
[79319]2492 strImageId = ValueUnion.psz;
[79942]2493 if (strImageId.isEmpty())
[92372]2494 return errorArgument(Cloud::tr("Empty parameter: --id"));
[79942]2495
[79319]2496 break;
[79942]2497 }
2498
[93872]2499 case 'h':
[83279]2500 printHelp(g_pStdOut);
2501 return RTEXITCODE_SUCCESS;
[79319]2502 case VINF_GETOPT_NOT_OPTION:
2503 return errorUnknownSubcommand(ValueUnion.psz);
[79942]2504
[79319]2505 default:
2506 return errorGetOpt(c, &ValueUnion);
2507 }
2508 }
2509
[83279]2510 /* Delayed check. It allows us to print help information.*/
2511 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2512 if (FAILED(hrc))
2513 return RTEXITCODE_FAILURE;
2514
[79980]2515 if (strImageId.isEmpty())
[92372]2516 return errorArgument(Cloud::tr("Missing parameter: --id"));
[79980]2517
2518
[79319]2519 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
2520
2521 ComObjPtr<ICloudClient> oCloudClient;
2522 CHECK_ERROR2_RET(hrc, pCloudProfile,
2523 CreateCloudClient(oCloudClient.asOutParam()),
2524 RTEXITCODE_FAILURE);
[92372]2525 RTPrintf(Cloud::tr("Deleting cloud image with id %s...\n"), strImageId.c_str());
[79319]2526
2527 ComPtr<IProgress> progress;
2528 CHECK_ERROR2_RET(hrc, oCloudClient,
[79943]2529 DeleteImage(Bstr(strImageId).raw(), progress.asOutParam()),
[79319]2530 RTEXITCODE_FAILURE);
2531 hrc = showProgress(progress);
[92372]2532 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Deleting cloud image failed")), RTEXITCODE_FAILURE);
[79319]2533
2534 if (SUCCEEDED(hrc))
[92594]2535 RTPrintf(Cloud::tr("Cloud image was deleted successfully\n"));
[79319]2536
2537 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2538}
2539
2540static RTEXITCODE handleCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2541{
[91133]2542 enum
2543 {
2544 kCloudImageIota = 1000,
2545 kCloudImage_Create,
2546 kCloudImage_Delete,
2547 kCloudImage_Export,
2548 kCloudImage_Import,
2549 kCloudImage_Info,
2550 kCloudImage_Update,
2551 };
2552
2553 static const RTGETOPTDEF s_aOptions[] =
2554 {
2555 { "create", kCloudImage_Create, RTGETOPT_REQ_NOTHING },
2556 { "delete", kCloudImage_Delete, RTGETOPT_REQ_NOTHING },
2557 { "export", kCloudImage_Export, RTGETOPT_REQ_NOTHING },
2558 { "import", kCloudImage_Import, RTGETOPT_REQ_NOTHING },
2559 { "info", kCloudImage_Info, RTGETOPT_REQ_NOTHING },
2560 { "update", kCloudImage_Update, RTGETOPT_REQ_NOTHING },
2561
2562 { "help", 'h', RTGETOPT_REQ_NOTHING },
2563 { "-?", 'h', RTGETOPT_REQ_NOTHING },
2564 { "-help", 'h', RTGETOPT_REQ_NOTHING },
2565 { "--help", 'h', RTGETOPT_REQ_NOTHING },
2566 };
2567
[83279]2568 if (a->argc == iFirst)
2569 {
[92372]2570 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
[83279]2571 printHelp(g_pStdOut);
2572 return RTEXITCODE_SUCCESS;
2573 }
[79319]2574
2575 RTGETOPTSTATE GetState;
2576 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2577 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2578
2579 int c;
2580 RTGETOPTUNION ValueUnion;
2581 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2582 {
2583 switch (c)
2584 {
2585 /* Sub-commands: */
[91133]2586 case kCloudImage_Create:
[99513]2587 setCurrentSubcommand(HELP_SCOPE_CLOUD_IMAGE_CREATE);
[79319]2588 return createCloudImage(a, GetState.iNext, pCommonOpts);
[91133]2589
2590 case kCloudImage_Export:
[99513]2591 setCurrentSubcommand(HELP_SCOPE_CLOUD_IMAGE_EXPORT);
[79319]2592 return exportCloudImage(a, GetState.iNext, pCommonOpts);
[91133]2593
2594 case kCloudImage_Import:
[99513]2595 setCurrentSubcommand(HELP_SCOPE_CLOUD_IMAGE_IMPORT);
[79319]2596 return importCloudImage(a, GetState.iNext, pCommonOpts);
[91133]2597
2598 case kCloudImage_Info:
[99513]2599 setCurrentSubcommand(HELP_SCOPE_CLOUD_IMAGE_INFO);
[79319]2600 return showCloudImageInfo(a, GetState.iNext, pCommonOpts);
[91133]2601
2602 case kCloudImage_Update:
[99513]2603// setCurrentSubcommand(HELP_SCOPE_CLOUD_IMAGE_UPDATE);
[79319]2604 return updateCloudImage(a, GetState.iNext, pCommonOpts);
[91133]2605
2606 case kCloudImage_Delete:
[99513]2607 setCurrentSubcommand(HELP_SCOPE_CLOUD_IMAGE_DELETE);
[79319]2608 return deleteCloudImage(a, GetState.iNext, pCommonOpts);
[91133]2609
2610 case 'h':
[83279]2611 printHelp(g_pStdOut);
2612 return RTEXITCODE_SUCCESS;
[91133]2613
[79319]2614 case VINF_GETOPT_NOT_OPTION:
2615 return errorUnknownSubcommand(ValueUnion.psz);
2616
2617 default:
2618 return errorGetOpt(c, &ValueUnion);
2619 }
2620 }
2621
2622 return errorNoSubcommand();
2623}
2624
[83169]2625#ifdef VBOX_WITH_CLOUD_NET
2626struct CloudNetworkOptions
2627{
2628 BOOL fEnable;
2629 BOOL fDisable;
2630 Bstr strNetworkId;
2631 Bstr strNetworkName;
2632};
2633typedef struct CloudNetworkOptions CLOUDNETOPT;
2634typedef CLOUDNETOPT *PCLOUDNETOPT;
2635
2636static RTEXITCODE createUpdateCloudNetworkCommon(ComPtr<ICloudNetwork> cloudNetwork, CLOUDNETOPT& options, PCLOUDCOMMONOPT pCommonOpts)
2637{
2638 HRESULT hrc = S_OK;
2639
2640 Bstr strProvider = pCommonOpts->provider.pszProviderName;
2641 Bstr strProfile = pCommonOpts->profile.pszProfileName;
2642
2643 if (options.fEnable)
[83170]2644 {
[83169]2645 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Enabled)(TRUE), RTEXITCODE_FAILURE);
[83170]2646 }
[83169]2647 if (options.fDisable)
[83170]2648 {
[83169]2649 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Enabled)(FALSE), RTEXITCODE_FAILURE);
[83170]2650 }
[83169]2651 if (options.strNetworkId.isNotEmpty())
[83170]2652 {
[83169]2653 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(NetworkId)(options.strNetworkId.raw()), RTEXITCODE_FAILURE);
[83170]2654 }
[83169]2655 if (strProvider.isNotEmpty())
[83170]2656 {
[83169]2657 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Provider)(strProvider.raw()), RTEXITCODE_FAILURE);
[83170]2658 }
[83169]2659 if (strProfile.isNotEmpty())
[83170]2660 {
[83169]2661 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Profile)(strProfile.raw()), RTEXITCODE_FAILURE);
[83170]2662 }
[83169]2663
2664 return RTEXITCODE_SUCCESS;
2665}
2666
2667
2668static RTEXITCODE createCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2669{
2670 HRESULT hrc = S_OK;
2671 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2672 if (FAILED(hrc))
2673 return RTEXITCODE_FAILURE;
2674
2675 /* Required parameters, the rest is handled in update */
2676 static const RTGETOPTDEF s_aOptions[] =
2677 {
2678 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
2679 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
2680 { "--network-id", 'i', RTGETOPT_REQ_STRING },
2681 { "--name", 'n', RTGETOPT_REQ_STRING },
2682 };
2683
2684 RTGETOPTSTATE GetState;
2685 RTGETOPTUNION ValueUnion;
2686 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2687 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2688
2689 CLOUDNETOPT options;
2690 options.fEnable = FALSE;
2691 options.fDisable = FALSE;
2692
2693 int c;
2694 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2695 {
2696 switch (c)
2697 {
2698 case 'd':
2699 options.fDisable = TRUE;
2700 break;
2701 case 'e':
2702 options.fEnable = TRUE;
2703 break;
2704 case 'i':
2705 options.strNetworkId=ValueUnion.psz;
2706 break;
2707 case 'n':
2708 options.strNetworkName=ValueUnion.psz;
2709 break;
2710 case VINF_GETOPT_NOT_OPTION:
2711 return errorUnknownSubcommand(ValueUnion.psz);
2712 default:
2713 return errorGetOpt(c, &ValueUnion);
2714 }
2715 }
2716
2717 if (options.strNetworkName.isEmpty())
[92372]2718 return errorArgument(Cloud::tr("Missing --name parameter"));
[83169]2719 if (options.strNetworkId.isEmpty())
[92372]2720 return errorArgument(Cloud::tr("Missing --network-id parameter"));
[83169]2721
2722 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2723
2724 ComPtr<ICloudNetwork> cloudNetwork;
2725 CHECK_ERROR2_RET(hrc, pVirtualBox,
2726 CreateCloudNetwork(options.strNetworkName.raw(), cloudNetwork.asOutParam()),
2727 RTEXITCODE_FAILURE);
2728
2729 /* Fill out the created network */
2730 RTEXITCODE rc = createUpdateCloudNetworkCommon(cloudNetwork, options, pCommonOpts);
2731 if (RT_SUCCESS(rc))
[92372]2732 RTPrintf(Cloud::tr("Cloud network was created successfully\n"));
[83169]2733
2734 return rc;
2735}
2736
2737
2738static RTEXITCODE showCloudNetworkInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2739{
2740 RT_NOREF(pCommonOpts);
2741 HRESULT hrc = S_OK;
2742 static const RTGETOPTDEF s_aOptions[] =
2743 {
2744 { "--name", 'n', RTGETOPT_REQ_STRING },
2745 };
2746 RTGETOPTSTATE GetState;
2747 RTGETOPTUNION ValueUnion;
2748 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2749 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2750
2751 Bstr strNetworkName;
2752
2753 int c;
2754 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2755 {
2756 switch (c)
2757 {
2758 case 'n':
2759 strNetworkName=ValueUnion.psz;
2760 break;
2761 case VINF_GETOPT_NOT_OPTION:
2762 return errorUnknownSubcommand(ValueUnion.psz);
2763 default:
2764 return errorGetOpt(c, &ValueUnion);
2765 }
2766 }
2767
2768 if (strNetworkName.isEmpty())
[92372]2769 return errorArgument(Cloud::tr("Missing --name parameter"));
[83169]2770
2771 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2772 ComPtr<ICloudNetwork> cloudNetwork;
2773 CHECK_ERROR2_RET(hrc, pVirtualBox,
2774 FindCloudNetworkByName(strNetworkName.raw(), cloudNetwork.asOutParam()),
2775 RTEXITCODE_FAILURE);
2776
[92372]2777 RTPrintf(Cloud::tr("Name: %ls\n"), strNetworkName.raw());
[83169]2778 BOOL fEnabled = FALSE;
2779 cloudNetwork->COMGETTER(Enabled)(&fEnabled);
[92372]2780 RTPrintf(Cloud::tr("State: %s\n"), fEnabled ? Cloud::tr("Enabled") : Cloud::tr("Disabled"));
[83169]2781 Bstr Provider;
2782 cloudNetwork->COMGETTER(Provider)(Provider.asOutParam());
[92372]2783 RTPrintf(Cloud::tr("CloudProvider: %ls\n"), Provider.raw());
[83169]2784 Bstr Profile;
2785 cloudNetwork->COMGETTER(Profile)(Profile.asOutParam());
[92372]2786 RTPrintf(Cloud::tr("CloudProfile: %ls\n"), Profile.raw());
[83169]2787 Bstr NetworkId;
2788 cloudNetwork->COMGETTER(NetworkId)(NetworkId.asOutParam());
[92372]2789 RTPrintf(Cloud::tr("CloudNetworkId: %ls\n"), NetworkId.raw());
[83169]2790 Bstr netName = BstrFmt("cloud-%ls", strNetworkName.raw());
[92372]2791 RTPrintf(Cloud::tr("VBoxNetworkName: %ls\n\n"), netName.raw());
[83169]2792
2793 return RTEXITCODE_SUCCESS;
2794}
2795
2796
2797static RTEXITCODE updateCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2798{
2799 HRESULT hrc = S_OK;
2800
2801 static const RTGETOPTDEF s_aOptions[] =
2802 {
2803 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
2804 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
2805 { "--network-id", 'i', RTGETOPT_REQ_STRING },
2806 { "--name", 'n', RTGETOPT_REQ_STRING },
2807 };
2808
2809 RTGETOPTSTATE GetState;
2810 RTGETOPTUNION ValueUnion;
2811 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2812 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2813
2814 CLOUDNETOPT options;
2815 options.fEnable = FALSE;
2816 options.fDisable = FALSE;
2817
2818 int c;
2819 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2820 {
2821 switch (c)
2822 {
2823 case 'd':
2824 options.fDisable = TRUE;
2825 break;
2826 case 'e':
2827 options.fEnable = TRUE;
2828 break;
2829 case 'i':
2830 options.strNetworkId=ValueUnion.psz;
2831 break;
2832 case 'n':
2833 options.strNetworkName=ValueUnion.psz;
2834 break;
2835 case VINF_GETOPT_NOT_OPTION:
2836 return errorUnknownSubcommand(ValueUnion.psz);
2837 default:
2838 return errorGetOpt(c, &ValueUnion);
2839 }
2840 }
2841
2842 if (options.strNetworkName.isEmpty())
[92372]2843 return errorArgument(Cloud::tr("Missing --name parameter"));
[83169]2844
2845 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2846 ComPtr<ICloudNetwork> cloudNetwork;
2847 CHECK_ERROR2_RET(hrc, pVirtualBox,
2848 FindCloudNetworkByName(options.strNetworkName.raw(), cloudNetwork.asOutParam()),
2849 RTEXITCODE_FAILURE);
2850
2851 RTEXITCODE rc = createUpdateCloudNetworkCommon(cloudNetwork, options, pCommonOpts);
2852 if (RT_SUCCESS(rc))
[92372]2853 RTPrintf(Cloud::tr("Cloud network %ls was updated successfully\n"), options.strNetworkName.raw());
[83169]2854
2855 return rc;
2856}
2857
2858
2859static RTEXITCODE deleteCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2860{
2861 RT_NOREF(pCommonOpts);
2862 HRESULT hrc = S_OK;
2863 static const RTGETOPTDEF s_aOptions[] =
2864 {
2865 { "--name", 'n', RTGETOPT_REQ_STRING },
2866 };
2867 RTGETOPTSTATE GetState;
2868 RTGETOPTUNION ValueUnion;
2869 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2870 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2871
2872 Bstr strNetworkName;
2873
2874 int c;
2875 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2876 {
2877 switch (c)
2878 {
2879 case 'n':
2880 strNetworkName=ValueUnion.psz;
2881 break;
2882 case VINF_GETOPT_NOT_OPTION:
2883 return errorUnknownSubcommand(ValueUnion.psz);
2884 default:
2885 return errorGetOpt(c, &ValueUnion);
2886 }
2887 }
2888
2889 if (strNetworkName.isEmpty())
[92372]2890 return errorArgument(Cloud::tr("Missing --name parameter"));
[83169]2891
2892 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2893 ComPtr<ICloudNetwork> cloudNetwork;
2894 CHECK_ERROR2_RET(hrc, pVirtualBox,
2895 FindCloudNetworkByName(strNetworkName.raw(), cloudNetwork.asOutParam()),
2896 RTEXITCODE_FAILURE);
2897
2898 CHECK_ERROR2_RET(hrc, pVirtualBox,
2899 RemoveCloudNetwork(cloudNetwork),
2900 RTEXITCODE_FAILURE);
2901
2902 if (SUCCEEDED(hrc))
[92372]2903 RTPrintf(Cloud::tr("Cloud network %ls was deleted successfully\n"), strNetworkName.raw());
[83169]2904
2905 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2906}
2907
2908
[84618]2909static RTEXITCODE setupCloudNetworkEnv(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2910{
2911 RT_NOREF(pCommonOpts);
2912 HRESULT hrc = S_OK;
2913 static const RTGETOPTDEF s_aOptions[] =
2914 {
2915 { "--gateway-os-name", 'n', RTGETOPT_REQ_STRING },
2916 { "--gateway-os-version", 'v', RTGETOPT_REQ_STRING },
2917 { "--gateway-shape", 's', RTGETOPT_REQ_STRING },
2918 { "--tunnel-network-name", 't', RTGETOPT_REQ_STRING },
2919 { "--tunnel-network-range", 'r', RTGETOPT_REQ_STRING },
[86153]2920 { "--compartment-id", 'c', RTGETOPT_REQ_STRING }
[84618]2921 };
2922 RTGETOPTSTATE GetState;
2923 RTGETOPTUNION ValueUnion;
2924 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2925 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2926
2927 Bstr strGatewayOsName;
2928 Bstr strGatewayOsVersion;
2929 Bstr strGatewayShape;
2930 Bstr strTunnelNetworkName;
2931 Bstr strTunnelNetworkRange;
[86153]2932 Bstr strCompartmentId;
[84618]2933
2934 int c;
2935 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2936 {
2937 switch (c)
2938 {
2939 case 'n':
2940 strGatewayOsName=ValueUnion.psz;
2941 break;
2942 case 'v':
2943 strGatewayOsVersion=ValueUnion.psz;
2944 break;
2945 case 's':
2946 strGatewayShape=ValueUnion.psz;
2947 break;
2948 case 't':
2949 strTunnelNetworkName=ValueUnion.psz;
2950 break;
2951 case 'r':
2952 strTunnelNetworkRange=ValueUnion.psz;
2953 break;
[86153]2954 case 'c':
2955 strCompartmentId=ValueUnion.psz;
2956 break;
[84618]2957 case VINF_GETOPT_NOT_OPTION:
2958 return errorUnknownSubcommand(ValueUnion.psz);
2959 default:
2960 return errorGetOpt(c, &ValueUnion);
2961 }
2962 }
2963
2964 /* Delayed check. It allows us to print help information.*/
2965 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2966 if (FAILED(hrc))
2967 return RTEXITCODE_FAILURE;
2968
[84639]2969 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2970
[92372]2971 RTPrintf(Cloud::tr("Setting up tunnel network in the cloud...\n"));
[84639]2972
[84618]2973 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
2974
[86153]2975 /* Use user-specified profile instead of default one. */
2976 if (strCompartmentId.isNotEmpty())
2977 {
2978 CHECK_ERROR2_RET(hrc, pCloudProfile,
2979 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),
2980 RTEXITCODE_FAILURE);
2981 }
2982
[84618]2983 ComObjPtr<ICloudClient> oCloudClient;
2984 CHECK_ERROR2_RET(hrc, pCloudProfile,
2985 CreateCloudClient(oCloudClient.asOutParam()),
2986 RTEXITCODE_FAILURE);
2987
2988 ComPtr<ICloudNetworkEnvironmentInfo> cloudNetworkEnv;
2989 ComPtr<IProgress> progress;
2990 CHECK_ERROR2_RET(hrc, oCloudClient,
2991 SetupCloudNetworkEnvironment(strTunnelNetworkName.raw(), strTunnelNetworkRange.raw(),
2992 strGatewayOsName.raw(), strGatewayOsVersion.raw(), strGatewayShape.raw(),
2993 cloudNetworkEnv.asOutParam(), progress.asOutParam()),
2994 RTEXITCODE_FAILURE);
2995
2996 hrc = showProgress(progress);
[92372]2997 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Setting up cloud network environment failed")), RTEXITCODE_FAILURE);
[84618]2998
2999 Bstr tunnelNetworkId;
3000 hrc = cloudNetworkEnv->COMGETTER(TunnelNetworkId)(tunnelNetworkId.asOutParam());
[92372]3001 RTPrintf(Cloud::tr("Cloud network environment was set up successfully. Tunnel network id is: %ls\n"), tunnelNetworkId.raw());
[84618]3002
3003 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
3004}
3005
3006
[83169]3007static RTEXITCODE handleCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
3008{
[91133]3009 enum
3010 {
3011 kCloudNetworkIota = 1000,
3012 kCloudNetwork_Create,
3013 kCloudNetwork_Delete,
3014 kCloudNetwork_Info,
3015 kCloudNetwork_Setup,
3016 kCloudNetwork_Update,
3017 };
[83169]3018
3019 static const RTGETOPTDEF s_aOptions[] =
3020 {
[91133]3021 { "create", kCloudNetwork_Create, RTGETOPT_REQ_NOTHING },
3022 { "delete", kCloudNetwork_Delete, RTGETOPT_REQ_NOTHING },
3023 { "info", kCloudNetwork_Info, RTGETOPT_REQ_NOTHING },
[91134]3024 { "setup", kCloudNetwork_Setup, RTGETOPT_REQ_NOTHING },
[91133]3025 { "update", kCloudNetwork_Update, RTGETOPT_REQ_NOTHING },
[83169]3026 };
3027
[91133]3028 if (a->argc < 1)
3029 return errorNoSubcommand();
3030
[83169]3031 RTGETOPTSTATE GetState;
3032 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
3033 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
3034
3035 int c;
3036 RTGETOPTUNION ValueUnion;
3037 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
3038 {
3039 switch (c)
3040 {
3041 /* Sub-commands: */
[91133]3042 case kCloudNetwork_Create:
[83169]3043 return createCloudNetwork(a, GetState.iNext, pCommonOpts);
[91133]3044
3045 case kCloudNetwork_Info:
[83169]3046 return showCloudNetworkInfo(a, GetState.iNext, pCommonOpts);
[91133]3047
3048 case kCloudNetwork_Update:
[83169]3049 return updateCloudNetwork(a, GetState.iNext, pCommonOpts);
[91133]3050
3051 case kCloudNetwork_Delete:
[83169]3052 return deleteCloudNetwork(a, GetState.iNext, pCommonOpts);
[91133]3053
3054 case kCloudNetwork_Setup:
[84618]3055 return setupCloudNetworkEnv(a, GetState.iNext, pCommonOpts);
[91133]3056
[83169]3057 case VINF_GETOPT_NOT_OPTION:
3058 return errorUnknownSubcommand(ValueUnion.psz);
3059
3060 default:
3061 return errorGetOpt(c, &ValueUnion);
3062 }
3063 }
3064
3065 return errorNoSubcommand();
3066}
3067#endif /* VBOX_WITH_CLOUD_NET */
3068
3069
[77883]3070RTEXITCODE handleCloud(HandlerArg *a)
3071{
[91133]3072 enum
3073 {
3074 kCloudIota = 1000,
3075 kCloud_Image,
3076 kCloud_Instance,
3077 kCloud_List,
3078 kCloud_Machine,
3079 kCloud_Network,
3080 kCloud_Object,
[91157]3081 kCloud_ShowVMInfo,
[91133]3082 kCloud_Volume,
3083 };
[77883]3084
3085 static const RTGETOPTDEF s_aOptions[] =
3086 {
3087 /* common options */
[91133]3088 { "--provider", 'v', RTGETOPT_REQ_STRING },
3089 { "--profile", 'f', RTGETOPT_REQ_STRING },
3090
3091 { "image", kCloud_Image, RTGETOPT_REQ_NOTHING },
3092 { "instance", kCloud_Instance, RTGETOPT_REQ_NOTHING },
3093 { "list", kCloud_List, RTGETOPT_REQ_NOTHING },
3094 { "machine", kCloud_Machine, RTGETOPT_REQ_NOTHING },
3095 { "network", kCloud_Network, RTGETOPT_REQ_NOTHING },
3096 { "object", kCloud_Object, RTGETOPT_REQ_NOTHING },
[91157]3097 { "showvminfo", kCloud_ShowVMInfo, RTGETOPT_REQ_NOTHING },
[91133]3098 { "volume", kCloud_Volume, RTGETOPT_REQ_NOTHING },
[77883]3099 };
3100
[91133]3101 if (a->argc < 1)
3102 return errorNoSubcommand();
3103
[77883]3104 RTGETOPTSTATE GetState;
3105 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
3106 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
3107
[78734]3108 CLOUDCOMMONOPT commonOpts = { {NULL, NULL}, {NULL, NULL} };
[77883]3109 int c;
3110 RTGETOPTUNION ValueUnion;
3111 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
3112 {
3113 switch (c)
3114 {
3115 case 'v': // --provider
[78734]3116 commonOpts.provider.pszProviderName = ValueUnion.psz;
[77883]3117 break;
[91133]3118
[77883]3119 case 'f': // --profile
[78734]3120 commonOpts.profile.pszProfileName = ValueUnion.psz;
[77883]3121 break;
[91133]3122
[77883]3123 /* Sub-commands: */
[91133]3124 case kCloud_List:
[78734]3125 return handleCloudLists(a, GetState.iNext, &commonOpts);
[91133]3126
3127 case kCloud_Image:
[79319]3128 return handleCloudImage(a, GetState.iNext, &commonOpts);
[91133]3129
3130 case kCloud_Instance:
[78734]3131 return handleCloudInstance(a, GetState.iNext, &commonOpts);
[91133]3132
[83169]3133#ifdef VBOX_WITH_CLOUD_NET
[91133]3134 case kCloud_Network:
[83169]3135 return handleCloudNetwork(a, GetState.iNext, &commonOpts);
3136#endif /* VBOX_WITH_CLOUD_NET */
[91133]3137
[91157]3138 /* "cloud machine ..." handling is in VBoxManageCloudMachine.cpp */
[91133]3139 case kCloud_Machine:
[90214]3140 return handleCloudMachine(a, GetState.iNext,
[90220]3141 commonOpts.provider.pszProviderName,
3142 commonOpts.profile.pszProfileName);
[90214]3143
[91157]3144 /* ... including aliases that mimic the local vm commands */
3145 case kCloud_ShowVMInfo:
3146 return handleCloudShowVMInfo(a, GetState.iNext,
3147 commonOpts.provider.pszProviderName,
3148 commonOpts.profile.pszProfileName);
3149
[77883]3150 case VINF_GETOPT_NOT_OPTION:
3151 return errorUnknownSubcommand(ValueUnion.psz);
3152
3153 default:
3154 return errorGetOpt(c, &ValueUnion);
3155 }
3156 }
3157
3158 return errorNoSubcommand();
3159}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use