VirtualBox

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

Last change on this file since 82781 was 82369, checked in by vboxsync, 5 years ago

Removed the unwanted argument in the calls AddDescription().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 60.3 KB
Line 
1/* $Id: VBoxManageCloud.cpp 82369 2019-12-04 09:52:43Z vboxsync $ */
2/** @file
3 * VBoxManageCloud - The cloud related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/com/com.h>
19#include <VBox/com/string.h>
20#include <VBox/com/Guid.h>
21#include <VBox/com/array.h>
22#include <VBox/com/ErrorInfo.h>
23#include <VBox/com/errorprint.h>
24#include <VBox/com/VirtualBox.h>
25
26#include <iprt/ctype.h>
27#include <iprt/getopt.h>
28#include <iprt/stream.h>
29#include <iprt/string.h>
30#include <iprt/uuid.h>
31#include <iprt/file.h>
32#include <VBox/log.h>
33
34#include "VBoxManage.h"
35
36#include <list>
37
38using namespace com;//at least for Bstr
39
40/**
41 * Common Cloud options.
42 */
43typedef struct
44{
45 struct {
46 const char *pszProviderName;
47 ComPtr<ICloudProvider> pCloudProvider;
48 }provider;
49 struct {
50 const char *pszProfileName;
51 ComPtr<ICloudProfile> pCloudProfile;
52 }profile;
53
54} CLOUDCOMMONOPT;
55typedef CLOUDCOMMONOPT *PCLOUDCOMMONOPT;
56
57static HRESULT checkAndSetCommonOptions(HandlerArg *a, PCLOUDCOMMONOPT pCommonOpts)
58{
59 HRESULT hrc = S_OK;
60
61 Bstr bstrProvider(pCommonOpts->provider.pszProviderName);
62 Bstr bstrProfile(pCommonOpts->profile.pszProfileName);
63
64 /* check for required options */
65 if (bstrProvider.isEmpty())
66 {
67 errorSyntax(USAGE_S_NEWCMD, "Parameter --provider is required");
68 return E_FAIL;
69 }
70 if (bstrProfile.isEmpty())
71 {
72 errorSyntax(USAGE_S_NEWCMD, "Parameter --profile is required");
73 return E_FAIL;
74 }
75
76 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
77 ComPtr<ICloudProviderManager> pCloudProviderManager;
78 CHECK_ERROR2_RET(hrc, pVirtualBox,
79 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
80 RTEXITCODE_FAILURE);
81
82 ComPtr<ICloudProvider> pCloudProvider;
83 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
84 GetProviderByShortName(bstrProvider.raw(), pCloudProvider.asOutParam()),
85 RTEXITCODE_FAILURE);
86 pCommonOpts->provider.pCloudProvider = pCloudProvider;
87
88 ComPtr<ICloudProfile> pCloudProfile;
89 CHECK_ERROR2_RET(hrc, pCloudProvider,
90 GetProfileByName(bstrProfile.raw(), pCloudProfile.asOutParam()),
91 RTEXITCODE_FAILURE);
92 pCommonOpts->profile.pCloudProfile = pCloudProfile;
93
94 return hrc;
95}
96
97
98/**
99 * List all available cloud instances for the specified cloud provider.
100 * Available cloud instance is one which state whether "running" or "stopped".
101 *
102 * @returns RTEXITCODE
103 * @param a is the list of passed arguments
104 * @param iFirst is the position of the first unparsed argument in the arguments list
105 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
106 * arguments which have been already parsed before
107 */
108static RTEXITCODE listCloudInstances(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
109{
110 static const RTGETOPTDEF s_aOptions[] =
111 {
112 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
113 { "--state", 's', RTGETOPT_REQ_STRING }
114 };
115 RTGETOPTSTATE GetState;
116 RTGETOPTUNION ValueUnion;
117 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
118 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
119
120 Utf8Str strCompartmentId;
121 com::SafeArray<CloudMachineState_T> machineStates;
122
123 int c;
124 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
125 {
126 switch (c)
127 {
128 case 'c':
129 strCompartmentId = ValueUnion.psz;
130 break;
131
132 case 's':
133 {
134 const char * const pszState = ValueUnion.psz;
135
136 if (RTStrICmp(pszState, "creatingimage") == 0)
137 machineStates.push_back(CloudMachineState_CreatingImage);
138 else if (RTStrICmp(pszState, "paused") == 0) /* XXX */
139 machineStates.push_back(CloudMachineState_Stopped);
140 else if (RTStrICmp(pszState, "provisioning") == 0)
141 machineStates.push_back(CloudMachineState_Provisioning);
142 else if (RTStrICmp(pszState, "running") == 0)
143 machineStates.push_back(CloudMachineState_Running);
144 else if (RTStrICmp(pszState, "starting") == 0)
145 machineStates.push_back(CloudMachineState_Starting);
146 else if (RTStrICmp(pszState, "stopped") == 0)
147 machineStates.push_back(CloudMachineState_Stopped);
148 else if (RTStrICmp(pszState, "stopping") == 0)
149 machineStates.push_back(CloudMachineState_Stopping);
150 else if (RTStrICmp(pszState, "terminated") == 0)
151 machineStates.push_back(CloudMachineState_Terminated);
152 else if (RTStrICmp(pszState, "terminating") == 0)
153 machineStates.push_back(CloudMachineState_Terminating);
154 else
155 return errorArgument("Unknown cloud instance state \"%s\"", pszState);
156 break;
157 }
158
159 case VINF_GETOPT_NOT_OPTION:
160 return errorUnknownSubcommand(ValueUnion.psz);
161
162 default:
163 return errorGetOpt(c, &ValueUnion);
164 }
165 }
166
167 HRESULT hrc = S_OK;
168 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
169
170 ComPtr<ICloudProviderManager> pCloudProviderManager;
171 CHECK_ERROR2_RET(hrc, pVirtualBox,
172 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
173 RTEXITCODE_FAILURE);
174
175 ComPtr<ICloudProvider> pCloudProvider;
176 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
177 GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()),
178 RTEXITCODE_FAILURE);
179
180 ComPtr<ICloudProfile> pCloudProfile;
181 CHECK_ERROR2_RET(hrc, pCloudProvider,
182 GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()),
183 RTEXITCODE_FAILURE);
184
185 if (strCompartmentId.isNotEmpty())
186 {
187 CHECK_ERROR2_RET(hrc, pCloudProfile,
188 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),
189 RTEXITCODE_FAILURE);
190 }
191 else
192 {
193 RTPrintf("Parameter \'compartment\' is empty or absent.\n"
194 "Trying to get the compartment from the passed cloud profile \'%s\'\n", pCommonOpts->profile.pszProfileName);
195 Bstr bStrCompartmentId;
196 CHECK_ERROR2_RET(hrc, pCloudProfile,
197 GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()),
198 RTEXITCODE_FAILURE);
199 strCompartmentId = bStrCompartmentId;
200 if (strCompartmentId.isNotEmpty())
201 RTPrintf("Found the compartment \'%s\':\n", strCompartmentId.c_str());
202 else
203 return errorSyntax(USAGE_S_NEWCMD, "Parameter --compartment-id is required");
204 }
205
206 Bstr bstrProfileName;
207 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
208
209 ComObjPtr<ICloudClient> oCloudClient;
210 CHECK_ERROR2_RET(hrc, pCloudProfile,
211 CreateCloudClient(oCloudClient.asOutParam()),
212 RTEXITCODE_FAILURE);
213
214 ComPtr<IStringArray> pVMNamesHolder;
215 ComPtr<IStringArray> pVMIdsHolder;
216 com::SafeArray<BSTR> arrayVMNames;
217 com::SafeArray<BSTR> arrayVMIds;
218 ComPtr<IProgress> pProgress;
219
220 RTPrintf("Reply is in the form \'instance name\' = \'instance id\'\n");
221
222 CHECK_ERROR2_RET(hrc, oCloudClient,
223 ListInstances(ComSafeArrayAsInParam(machineStates),
224 pVMNamesHolder.asOutParam(),
225 pVMIdsHolder.asOutParam(),
226 pProgress.asOutParam()),
227 RTEXITCODE_FAILURE);
228 showProgress(pProgress);
229 CHECK_PROGRESS_ERROR_RET(pProgress, ("Failed to list instances"), RTEXITCODE_FAILURE);
230
231 CHECK_ERROR2_RET(hrc,
232 pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)),
233 RTEXITCODE_FAILURE);
234 CHECK_ERROR2_RET(hrc,
235 pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)),
236 RTEXITCODE_FAILURE);
237
238 RTPrintf("The list of the instances for the cloud profile \'%ls\' \nand compartment \'%s\':\n",
239 bstrProfileName.raw(), strCompartmentId.c_str());
240 size_t cIds = arrayVMIds.size();
241 size_t cNames = arrayVMNames.size();
242 for (size_t k = 0; k < cNames; k++)
243 {
244 Bstr value;
245 if (k < cIds)
246 value = arrayVMIds[k];
247 RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw());
248 }
249
250 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
251}
252
253
254/**
255 * List all available cloud images for the specified cloud provider.
256 *
257 * @returns RTEXITCODE
258 * @param a is the list of passed arguments
259 * @param iFirst is the position of the first unparsed argument in the arguments list
260 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
261 * arguments which have been already parsed before
262 */
263static RTEXITCODE listCloudImages(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
264{
265 static const RTGETOPTDEF s_aOptions[] =
266 {
267 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
268 { "--state", 's', RTGETOPT_REQ_STRING }
269 };
270 RTGETOPTSTATE GetState;
271 RTGETOPTUNION ValueUnion;
272 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
273 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
274
275 Utf8Str strCompartmentId;
276 com::SafeArray<CloudImageState_T> imageStates;
277
278 int c;
279 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
280 {
281 switch (c)
282 {
283 case 'c':
284 strCompartmentId = ValueUnion.psz;
285 break;
286
287 case 's':
288 {
289 const char * const pszState = ValueUnion.psz;
290
291 if (RTStrICmp(pszState, "available") == 0)
292 imageStates.push_back(CloudImageState_Available);
293 else if (RTStrICmp(pszState, "deleted") == 0)
294 imageStates.push_back(CloudImageState_Deleted);
295 else if (RTStrICmp(pszState, "disabled") == 0)
296 imageStates.push_back(CloudImageState_Disabled);
297 else if (RTStrICmp(pszState, "exporting") == 0)
298 imageStates.push_back(CloudImageState_Exporting);
299 else if (RTStrICmp(pszState, "importing") == 0)
300 imageStates.push_back(CloudImageState_Importing);
301 else if (RTStrICmp(pszState, "provisioning") == 0)
302 imageStates.push_back(CloudImageState_Provisioning);
303 else
304 return errorArgument("Unknown cloud image state \"%s\"", pszState);
305 break;
306 }
307
308 case VINF_GETOPT_NOT_OPTION:
309 return errorUnknownSubcommand(ValueUnion.psz);
310
311 default:
312 return errorGetOpt(c, &ValueUnion);
313 }
314 }
315
316
317 HRESULT hrc = S_OK;
318 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
319
320 ComPtr<ICloudProviderManager> pCloudProviderManager;
321 CHECK_ERROR2_RET(hrc, pVirtualBox,
322 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
323 RTEXITCODE_FAILURE);
324
325 ComPtr<ICloudProvider> pCloudProvider;
326 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
327 GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()),
328 RTEXITCODE_FAILURE);
329
330 ComPtr<ICloudProfile> pCloudProfile;
331 CHECK_ERROR2_RET(hrc, pCloudProvider,
332 GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()),
333 RTEXITCODE_FAILURE);
334
335 if (strCompartmentId.isNotEmpty())
336 {
337 CHECK_ERROR2_RET(hrc, pCloudProfile,
338 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),\
339 RTEXITCODE_FAILURE);
340 }
341 else
342 {
343 RTPrintf("Parameter \'compartment\' is empty or absent.\n"
344 "Trying to get the compartment from the passed cloud profile \'%s\'\n", pCommonOpts->profile.pszProfileName);
345 Bstr bStrCompartmentId;
346 CHECK_ERROR2_RET(hrc, pCloudProfile,
347 GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()),
348 RTEXITCODE_FAILURE);
349 strCompartmentId = bStrCompartmentId;
350 if (strCompartmentId.isNotEmpty())
351 RTPrintf("Found the compartment \'%s\':\n", strCompartmentId.c_str());
352 else
353 return errorSyntax(USAGE_S_NEWCMD, "Parameter --compartment-id is required");
354 }
355
356 Bstr bstrProfileName;
357 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
358
359 ComObjPtr<ICloudClient> oCloudClient;
360 CHECK_ERROR2_RET(hrc, pCloudProfile,
361 CreateCloudClient(oCloudClient.asOutParam()),
362 RTEXITCODE_FAILURE);
363
364 ComPtr<IStringArray> pVMNamesHolder;
365 ComPtr<IStringArray> pVMIdsHolder;
366 com::SafeArray<BSTR> arrayVMNames;
367 com::SafeArray<BSTR> arrayVMIds;
368 ComPtr<IProgress> pProgress;
369
370 RTPrintf("Reply is in the form \'image name\' = \'image id\'\n");
371 CHECK_ERROR2_RET(hrc, oCloudClient,
372 ListImages(ComSafeArrayAsInParam(imageStates),
373 pVMNamesHolder.asOutParam(),
374 pVMIdsHolder.asOutParam(),
375 pProgress.asOutParam()),
376 RTEXITCODE_FAILURE);
377 showProgress(pProgress);
378 CHECK_PROGRESS_ERROR_RET(pProgress, ("Failed to list images"), RTEXITCODE_FAILURE);
379
380 CHECK_ERROR2_RET(hrc,
381 pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)),
382 RTEXITCODE_FAILURE);
383 CHECK_ERROR2_RET(hrc,
384 pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)),
385 RTEXITCODE_FAILURE);
386
387 RTPrintf("The list of the images for the cloud profile \'%ls\' \nand compartment \'%s\':\n",
388 bstrProfileName.raw(), strCompartmentId.c_str());
389 size_t cNames = arrayVMNames.size();
390 size_t cIds = arrayVMIds.size();
391 for (size_t k = 0; k < cNames; k++)
392 {
393 Bstr value;
394 if (k < cIds)
395 value = arrayVMIds[k];
396 RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw());
397 }
398
399 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
400}
401
402/**
403 * General function which handles the "list" commands
404 *
405 * @returns RTEXITCODE
406 * @param a is the list of passed arguments
407 * @param iFirst is the position of the first unparsed argument in the arguments list
408 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
409 * arguments which have been already parsed before
410 */
411static RTEXITCODE handleCloudLists(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
412{
413 if (a->argc < 1)
414 return errorNoSubcommand();
415
416 static const RTGETOPTDEF s_aOptions[] =
417 {
418 { "images", 1000, RTGETOPT_REQ_NOTHING },
419 { "instances", 1001, RTGETOPT_REQ_NOTHING },
420 { "networks", 1002, RTGETOPT_REQ_NOTHING },
421 { "subnets", 1003, RTGETOPT_REQ_NOTHING },
422 { "vcns", 1004, RTGETOPT_REQ_NOTHING },
423 { "objects", 1005, RTGETOPT_REQ_NOTHING }
424 };
425
426 Bstr bstrProvider(pCommonOpts->provider.pszProviderName);
427 Bstr bstrProfile(pCommonOpts->profile.pszProfileName);
428
429 /* check for required options */
430 if (bstrProvider.isEmpty())
431 return errorSyntax(USAGE_S_NEWCMD, "Parameter --provider is required");
432 if (bstrProfile.isEmpty())
433 return errorSyntax(USAGE_S_NEWCMD, "Parameter --profile is required");
434
435 RTGETOPTSTATE GetState;
436 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
437 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
438
439 int c;
440 RTGETOPTUNION ValueUnion;
441 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
442 {
443 switch (c)
444 {
445 case 1000:
446// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_LIST);
447 return listCloudImages(a, GetState.iNext, pCommonOpts);
448 case 1001:
449// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_LIST);
450 return listCloudInstances(a, GetState.iNext, pCommonOpts);
451 case VINF_GETOPT_NOT_OPTION:
452 return errorUnknownSubcommand(ValueUnion.psz);
453
454 default:
455 return errorGetOpt(c, &ValueUnion);
456 }
457 }
458
459 return errorNoSubcommand();
460}
461
462static RTEXITCODE createCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
463{
464 HRESULT hrc = S_OK;
465 hrc = checkAndSetCommonOptions(a, pCommonOpts);
466 if (FAILED(hrc))
467 return RTEXITCODE_FAILURE;
468
469 static const RTGETOPTDEF s_aOptions[] =
470 {
471 { "--image-id", 'i', RTGETOPT_REQ_STRING },
472 { "--boot-volume-id", 'v', RTGETOPT_REQ_STRING },
473 { "--display-name", 'n', RTGETOPT_REQ_STRING },
474 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
475 { "--shape", 's', RTGETOPT_REQ_STRING },
476 { "--domain-name", 'd', RTGETOPT_REQ_STRING },
477 { "--boot-disk-size", 'b', RTGETOPT_REQ_STRING },
478 { "--publicip", 'p', RTGETOPT_REQ_STRING },
479 { "--subnet", 't', RTGETOPT_REQ_STRING },
480 { "--privateip", 'P', RTGETOPT_REQ_STRING },
481 { "--launch", 'l', RTGETOPT_REQ_STRING },
482 { "--public-ssh-key", 'k', RTGETOPT_REQ_STRING },
483 };
484 RTGETOPTSTATE GetState;
485 RTGETOPTUNION ValueUnion;
486 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
487 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
488
489 ComPtr<IAppliance> pAppliance;
490 CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE);
491 ULONG vsdNum = 1;
492 CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(1, &vsdNum), RTEXITCODE_FAILURE);
493 com::SafeIfaceArray<IVirtualSystemDescription> virtualSystemDescriptions;
494 CHECK_ERROR2_RET(hrc, pAppliance,
495 COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(virtualSystemDescriptions)),
496 RTEXITCODE_FAILURE);
497 ComPtr<IVirtualSystemDescription> pVSD = virtualSystemDescriptions[0];
498
499 Utf8Str strDisplayName, strImageId, strBootVolumeId, strPublicSSHKey;
500 int c;
501 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
502 {
503 switch (c)
504 {
505 case 'i':
506 strImageId = ValueUnion.psz;
507 pVSD->AddDescription(VirtualSystemDescriptionType_CloudImageId,
508 Bstr(ValueUnion.psz).raw(), NULL);
509 break;
510
511 case 'v':
512 strBootVolumeId = ValueUnion.psz;
513 pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootVolumeId,
514 Bstr(ValueUnion.psz).raw(), NULL);
515 break;
516 case 'n':
517 strDisplayName = ValueUnion.psz;
518 pVSD->AddDescription(VirtualSystemDescriptionType_Name,
519 Bstr(ValueUnion.psz).raw(), NULL);
520 break;
521 case 'm':
522 pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCILaunchMode,
523 Bstr(ValueUnion.psz).raw(), NULL);
524 break;
525 case 's':
526 pVSD->AddDescription(VirtualSystemDescriptionType_CloudInstanceShape,
527 Bstr(ValueUnion.psz).raw(), NULL);
528 break;
529 case 'd':
530 pVSD->AddDescription(VirtualSystemDescriptionType_CloudDomain,
531 Bstr(ValueUnion.psz).raw(), NULL);
532 break;
533 case 'b':
534 pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootDiskSize,
535 Bstr(ValueUnion.psz).raw(), NULL);
536 break;
537 case 'p':
538 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicIP,
539 Bstr(ValueUnion.psz).raw(), NULL);
540 break;
541 case 'P':
542 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPrivateIP,
543 Bstr(ValueUnion.psz).raw(), NULL);
544 break;
545 case 't':
546 pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCISubnet,
547 Bstr(ValueUnion.psz).raw(), NULL);
548 break;
549 case 'l':
550 {
551 Utf8Str strLaunch(ValueUnion.psz);
552 if (strLaunch.isNotEmpty() && (strLaunch.equalsIgnoreCase("true") || strLaunch.equalsIgnoreCase("false")))
553 pVSD->AddDescription(VirtualSystemDescriptionType_CloudLaunchInstance,
554 Bstr(ValueUnion.psz).raw(), NULL);
555 break;
556 }
557 case 'k':
558 strPublicSSHKey = ValueUnion.psz;
559 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicSSHKey,
560 Bstr(ValueUnion.psz).raw(), NULL);
561 break;
562 case VINF_GETOPT_NOT_OPTION:
563 return errorUnknownSubcommand(ValueUnion.psz);
564 default:
565 return errorGetOpt(c, &ValueUnion);
566 }
567 }
568
569 if (strPublicSSHKey.isEmpty())
570 RTPrintf("Warning!!! Public SSH key doesn't present in the passed arguments...\n");
571
572 if (strImageId.isNotEmpty() && strBootVolumeId.isNotEmpty())
573 return errorArgument("Parameters --image-id and --boot-volume-id are mutually exclusive. "
574 "Only one of them must be presented.");
575
576 if (strImageId.isEmpty() && strBootVolumeId.isEmpty())
577 return errorArgument("Missing parameter --image-id or --boot-volume-id. One of them must be presented.");
578
579 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
580
581 pVSD->AddDescription(VirtualSystemDescriptionType_CloudProfileName,
582 Bstr(pCommonOpts->profile.pszProfileName).raw(),
583 NULL);
584
585 ComObjPtr<ICloudClient> oCloudClient;
586 CHECK_ERROR2_RET(hrc, pCloudProfile,
587 CreateCloudClient(oCloudClient.asOutParam()),
588 RTEXITCODE_FAILURE);
589
590 ComPtr<IStringArray> infoArray;
591 com::SafeArray<BSTR> pStrInfoArray;
592 ComPtr<IProgress> pProgress;
593
594#if 0
595 /*
596 * OCI API returns an error during an instance creation if the image isn't available
597 * or in the inappropriate state. So the check can be omitted.
598 */
599 RTPrintf("Checking the cloud image with id \'%s\'...\n", strImageId.c_str());
600 CHECK_ERROR2_RET(hrc, oCloudClient,
601 GetImageInfo(Bstr(strImageId).raw(),
602 infoArray.asOutParam(),
603 pProgress.asOutParam()),
604 RTEXITCODE_FAILURE);
605
606 hrc = showProgress(pProgress);
607 CHECK_PROGRESS_ERROR_RET(pProgress, ("Checking the cloud image failed"), RTEXITCODE_FAILURE);
608
609 pProgress.setNull();
610#endif
611
612 if (strImageId.isNotEmpty())
613 RTPrintf("Creating cloud instance with name \'%s\' from the image \'%s\'...\n",
614 strDisplayName.c_str(), strImageId.c_str());
615 else
616 RTPrintf("Creating cloud instance with name \'%s\' from the boot volume \'%s\'...\n",
617 strDisplayName.c_str(), strBootVolumeId.c_str());
618
619 CHECK_ERROR2_RET(hrc, oCloudClient, LaunchVM(pVSD, pProgress.asOutParam()), RTEXITCODE_FAILURE);
620
621 hrc = showProgress(pProgress);
622 CHECK_PROGRESS_ERROR_RET(pProgress, ("Creating cloud instance failed"), RTEXITCODE_FAILURE);
623
624 if (SUCCEEDED(hrc))
625 RTPrintf("Cloud instance was created successfully\n");
626
627 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
628}
629
630static RTEXITCODE updateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
631{
632 RT_NOREF(a);
633 RT_NOREF(iFirst);
634 RT_NOREF(pCommonOpts);
635 return RTEXITCODE_SUCCESS;
636}
637
638static RTEXITCODE showCloudInstanceInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
639{
640 HRESULT hrc = S_OK;
641
642 hrc = checkAndSetCommonOptions(a, pCommonOpts);
643 if (FAILED(hrc))
644 return RTEXITCODE_FAILURE;
645
646 static const RTGETOPTDEF s_aOptions[] =
647 {
648 { "--id", 'i', RTGETOPT_REQ_STRING }
649 };
650 RTGETOPTSTATE GetState;
651 RTGETOPTUNION ValueUnion;
652 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
653 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
654
655 Utf8Str strInstanceId;
656
657 int c;
658 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
659 {
660 switch (c)
661 {
662 case 'i':
663 {
664 if (strInstanceId.isNotEmpty())
665 return errorArgument("Duplicate parameter: --id");
666
667 strInstanceId = ValueUnion.psz;
668 if (strInstanceId.isEmpty())
669 return errorArgument("Empty parameter: --id");
670
671 break;
672 }
673
674 case VINF_GETOPT_NOT_OPTION:
675 return errorUnknownSubcommand(ValueUnion.psz);
676
677 default:
678 return errorGetOpt(c, &ValueUnion);
679 }
680 }
681
682 if (strInstanceId.isEmpty())
683 return errorArgument("Missing parameter: --id");
684
685
686 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
687
688 ComObjPtr<ICloudClient> oCloudClient;
689 CHECK_ERROR2_RET(hrc, pCloudProfile,
690 CreateCloudClient(oCloudClient.asOutParam()),
691 RTEXITCODE_FAILURE);
692 RTPrintf("Getting information about cloud instance with id %s...\n", strInstanceId.c_str());
693 RTPrintf("Reply is in the form \'setting name\' = \'value\'\n");
694
695 ComPtr<IAppliance> pAppliance;
696 CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE);
697
698 com::SafeIfaceArray<IVirtualSystemDescription> vsdArray;
699 ULONG requestedVSDnums = 1;
700 ULONG newVSDnums = 0;
701 CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(requestedVSDnums, &newVSDnums), RTEXITCODE_FAILURE);
702 if (requestedVSDnums != newVSDnums)
703 return RTEXITCODE_FAILURE;
704
705 CHECK_ERROR2_RET(hrc, pAppliance, COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(vsdArray)), RTEXITCODE_FAILURE);
706 ComPtr<IVirtualSystemDescription> instanceDescription = vsdArray[0];
707
708 ComPtr<IProgress> progress;
709 CHECK_ERROR2_RET(hrc, oCloudClient,
710 GetInstanceInfo(Bstr(strInstanceId).raw(), instanceDescription, progress.asOutParam()),
711 RTEXITCODE_FAILURE);
712
713 hrc = showProgress(progress);
714 CHECK_PROGRESS_ERROR_RET(progress, ("Getting information about cloud instance failed"), RTEXITCODE_FAILURE);
715
716 RTPrintf("Cloud instance info (provider '%s'):\n",
717 pCommonOpts->provider.pszProviderName);
718
719 struct vsdHReadable {
720 VirtualSystemDescriptionType_T vsdType;
721 Utf8Str strFound;
722 Utf8Str strNotFound;
723 };
724
725 const size_t vsdHReadableArraySize = 12;//the number of items in the vsdHReadableArray
726 vsdHReadable vsdHReadableArray[vsdHReadableArraySize] = {
727 {VirtualSystemDescriptionType_CloudDomain, "Availability domain = %ls\n", "Availability domain wasn't found\n"},
728 {VirtualSystemDescriptionType_Name, "Instance displayed name = %ls\n", "Instance displayed name wasn't found\n"},
729 {VirtualSystemDescriptionType_CloudInstanceState, "Instance state = %ls\n", "Instance state wasn't found\n"},
730 {VirtualSystemDescriptionType_CloudInstanceId, "Instance Id = %ls\n", "Instance Id wasn't found\n"},
731 {VirtualSystemDescriptionType_CloudInstanceDisplayName, "Instance name = %ls\n", "Instance name wasn't found\n"},
732 {VirtualSystemDescriptionType_CloudImageId, "Bootable image Id = %ls\n",
733 "Image Id whom the instance is booted up wasn't found\n"},
734 {VirtualSystemDescriptionType_CloudInstanceShape, "Shape of the instance = %ls\n",
735 "The shape of the instance wasn't found\n"},
736 {VirtualSystemDescriptionType_OS, "Type of guest OS = %ls\n", "Type of guest OS wasn't found\n"},
737 {VirtualSystemDescriptionType_Memory, "RAM = %ls MB\n", "Value for RAM wasn't found\n"},
738 {VirtualSystemDescriptionType_CPU, "CPUs = %ls\n", "Numbers of CPUs weren't found\n"},
739 {VirtualSystemDescriptionType_CloudPublicIP, "Instance public IP = %ls\n", "Public IP wasn't found\n"},
740 {VirtualSystemDescriptionType_Miscellaneous, "%ls\n", "Free-form tags or metadata weren't found\n"}
741 };
742
743 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
744 com::SafeArray<BSTR> aRefs;
745 com::SafeArray<BSTR> aOvfValues;
746 com::SafeArray<BSTR> aVBoxValues;
747 com::SafeArray<BSTR> aExtraConfigValues;
748
749 for (size_t i=0; i<vsdHReadableArraySize ; ++i)
750 {
751 hrc = instanceDescription->GetDescriptionByType(vsdHReadableArray[i].vsdType,
752 ComSafeArrayAsOutParam(retTypes),
753 ComSafeArrayAsOutParam(aRefs),
754 ComSafeArrayAsOutParam(aOvfValues),
755 ComSafeArrayAsOutParam(aVBoxValues),
756 ComSafeArrayAsOutParam(aExtraConfigValues));
757 if (FAILED(hrc) || aVBoxValues.size() == 0)
758 LogRel((vsdHReadableArray[i].strNotFound.c_str()));
759 else
760 {
761 LogRel(("Size is %d", aVBoxValues.size()));
762 for (size_t j = 0; j<aVBoxValues.size(); ++j)
763 {
764 RTPrintf(vsdHReadableArray[i].strFound.c_str(), aVBoxValues[j]);
765 }
766 }
767
768 retTypes.setNull();
769 aRefs.setNull();
770 aOvfValues.setNull();
771 aVBoxValues.setNull();
772 aExtraConfigValues.setNull();
773 }
774
775 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
776}
777
778static RTEXITCODE startCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
779{
780 HRESULT hrc = S_OK;
781 hrc = checkAndSetCommonOptions(a, pCommonOpts);
782 if (FAILED(hrc))
783 return RTEXITCODE_FAILURE;
784
785 static const RTGETOPTDEF s_aOptions[] =
786 {
787 { "--id", 'i', RTGETOPT_REQ_STRING }
788 };
789 RTGETOPTSTATE GetState;
790 RTGETOPTUNION ValueUnion;
791 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
792 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
793
794 Utf8Str strInstanceId;
795
796 int c;
797 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
798 {
799 switch (c)
800 {
801 case 'i':
802 {
803 if (strInstanceId.isNotEmpty())
804 return errorArgument("Duplicate parameter: --id");
805
806 strInstanceId = ValueUnion.psz;
807 if (strInstanceId.isEmpty())
808 return errorArgument("Empty parameter: --id");
809
810 break;
811 }
812
813 case VINF_GETOPT_NOT_OPTION:
814 return errorUnknownSubcommand(ValueUnion.psz);
815
816 default:
817 return errorGetOpt(c, &ValueUnion);
818 }
819 }
820
821 if (strInstanceId.isEmpty())
822 return errorArgument("Missing parameter: --id");
823
824
825 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
826
827 ComObjPtr<ICloudClient> oCloudClient;
828 CHECK_ERROR2_RET(hrc, pCloudProfile,
829 CreateCloudClient(oCloudClient.asOutParam()),
830 RTEXITCODE_FAILURE);
831 RTPrintf("Starting cloud instance with id %s...\n", strInstanceId.c_str());
832
833 ComPtr<IProgress> progress;
834 CHECK_ERROR2_RET(hrc, oCloudClient,
835 StartInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
836 RTEXITCODE_FAILURE);
837 hrc = showProgress(progress);
838 CHECK_PROGRESS_ERROR_RET(progress, ("Starting the cloud instance failed"), RTEXITCODE_FAILURE);
839
840 if (SUCCEEDED(hrc))
841 RTPrintf("Cloud instance with id %s (provider = '%s', profile = '%s') was started\n",
842 strInstanceId.c_str(),
843 pCommonOpts->provider.pszProviderName,
844 pCommonOpts->profile.pszProfileName);
845
846 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
847}
848
849static RTEXITCODE pauseCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
850{
851 HRESULT hrc = S_OK;
852 hrc = checkAndSetCommonOptions(a, pCommonOpts);
853
854 if (FAILED(hrc))
855 return RTEXITCODE_FAILURE;
856
857 static const RTGETOPTDEF s_aOptions[] =
858 {
859 { "--id", 'i', RTGETOPT_REQ_STRING }
860 };
861 RTGETOPTSTATE GetState;
862 RTGETOPTUNION ValueUnion;
863 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
864 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
865
866 Utf8Str strInstanceId;
867
868 int c;
869 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
870 {
871 switch (c)
872 {
873 case 'i':
874 {
875 if (strInstanceId.isNotEmpty())
876 return errorArgument("Duplicate parameter: --id");
877
878 strInstanceId = ValueUnion.psz;
879 if (strInstanceId.isEmpty())
880 return errorArgument("Empty parameter: --id");
881
882 break;
883 }
884
885 case VINF_GETOPT_NOT_OPTION:
886 return errorUnknownSubcommand(ValueUnion.psz);
887
888 default:
889 return errorGetOpt(c, &ValueUnion);
890 }
891 }
892
893 if (strInstanceId.isEmpty())
894 return errorArgument("Missing parameter: --id");
895
896
897 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
898
899 ComObjPtr<ICloudClient> oCloudClient;
900 CHECK_ERROR2_RET(hrc, pCloudProfile,
901 CreateCloudClient(oCloudClient.asOutParam()),
902 RTEXITCODE_FAILURE);
903 RTPrintf("Pausing cloud instance with id %s...\n", strInstanceId.c_str());
904
905 ComPtr<IProgress> progress;
906 CHECK_ERROR2_RET(hrc, oCloudClient,
907 PauseInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
908 RTEXITCODE_FAILURE);
909 hrc = showProgress(progress);
910 CHECK_PROGRESS_ERROR_RET(progress, ("Pause the cloud instance failed"), RTEXITCODE_FAILURE);
911
912 if (SUCCEEDED(hrc))
913 RTPrintf("Cloud instance with id %s (provider = '%s', profile = '%s') was paused\n",
914 strInstanceId.c_str(),
915 pCommonOpts->provider.pszProviderName,
916 pCommonOpts->profile.pszProfileName);
917
918 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
919}
920
921static RTEXITCODE terminateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
922{
923 HRESULT hrc = S_OK;
924
925 hrc = checkAndSetCommonOptions(a, pCommonOpts);
926 if (FAILED(hrc))
927 return RTEXITCODE_FAILURE;
928
929 static const RTGETOPTDEF s_aOptions[] =
930 {
931 { "--id", 'i', RTGETOPT_REQ_STRING }
932 };
933 RTGETOPTSTATE GetState;
934 RTGETOPTUNION ValueUnion;
935 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
936 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
937
938 Utf8Str strInstanceId;
939
940 int c;
941 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
942 {
943 switch (c)
944 {
945 case 'i':
946 {
947 if (strInstanceId.isNotEmpty())
948 return errorArgument("Duplicate parameter: --id");
949
950 strInstanceId = ValueUnion.psz;
951 if (strInstanceId.isEmpty())
952 return errorArgument("Empty parameter: --id");
953
954 break;
955 }
956
957 case VINF_GETOPT_NOT_OPTION:
958 return errorUnknownSubcommand(ValueUnion.psz);
959
960 default:
961 return errorGetOpt(c, &ValueUnion);
962 }
963 }
964
965 if (strInstanceId.isEmpty())
966 return errorArgument("Missing parameter: --id");
967
968
969 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
970
971 ComObjPtr<ICloudClient> oCloudClient;
972 CHECK_ERROR2_RET(hrc, pCloudProfile,
973 CreateCloudClient(oCloudClient.asOutParam()),
974 RTEXITCODE_FAILURE);
975 RTPrintf("Terminating cloud instance with id %s...\n", strInstanceId.c_str());
976
977 ComPtr<IProgress> progress;
978 CHECK_ERROR2_RET(hrc, oCloudClient,
979 TerminateInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
980 RTEXITCODE_FAILURE);
981 hrc = showProgress(progress);
982 CHECK_PROGRESS_ERROR_RET(progress, ("Termination the cloud instance failed"), RTEXITCODE_FAILURE);
983
984 if (SUCCEEDED(hrc))
985 RTPrintf("Cloud instance with id %s (provider = '%s', profile = '%s') was terminated\n",
986 strInstanceId.c_str(),
987 pCommonOpts->provider.pszProviderName,
988 pCommonOpts->profile.pszProfileName);
989
990 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
991}
992
993static RTEXITCODE handleCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
994{
995 if (a->argc < 1)
996 return errorNoSubcommand();
997
998 static const RTGETOPTDEF s_aOptions[] =
999 {
1000 { "create", 1000, RTGETOPT_REQ_NOTHING },
1001 { "start", 1001, RTGETOPT_REQ_NOTHING },
1002 { "pause", 1002, RTGETOPT_REQ_NOTHING },
1003 { "info", 1003, RTGETOPT_REQ_NOTHING },
1004 { "update", 1004, RTGETOPT_REQ_NOTHING },
1005 { "terminate", 1005, RTGETOPT_REQ_NOTHING }
1006 };
1007
1008 RTGETOPTSTATE GetState;
1009 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1010 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1011
1012 int c;
1013 RTGETOPTUNION ValueUnion;
1014 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1015 {
1016 switch (c)
1017 {
1018 /* Sub-commands: */
1019 case 1000:
1020// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_CREATE);
1021 return createCloudInstance(a, GetState.iNext, pCommonOpts);
1022 case 1001:
1023 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_START);
1024 return startCloudInstance(a, GetState.iNext, pCommonOpts);
1025 case 1002:
1026 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_PAUSE);
1027 return pauseCloudInstance(a, GetState.iNext, pCommonOpts);
1028 case 1003:
1029 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_INFO);
1030 return showCloudInstanceInfo(a, GetState.iNext, pCommonOpts);
1031 case 1004:
1032// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_UPDATE);
1033 return updateCloudInstance(a, GetState.iNext, pCommonOpts);
1034 case 1005:
1035 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_TERMINATE);
1036 return terminateCloudInstance(a, GetState.iNext, pCommonOpts);
1037 case VINF_GETOPT_NOT_OPTION:
1038 return errorUnknownSubcommand(ValueUnion.psz);
1039
1040 default:
1041 return errorGetOpt(c, &ValueUnion);
1042 }
1043 }
1044
1045 return errorNoSubcommand();
1046}
1047
1048
1049static RTEXITCODE createCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1050{
1051 HRESULT hrc = S_OK;
1052 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1053 if (FAILED(hrc))
1054 return RTEXITCODE_FAILURE;
1055
1056 static const RTGETOPTDEF s_aOptions[] =
1057 {
1058 { "--object-name", 'o', RTGETOPT_REQ_STRING },
1059 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
1060 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
1061 { "--instance-id", 'i', RTGETOPT_REQ_STRING },
1062 { "--display-name", 'd', RTGETOPT_REQ_STRING },
1063 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
1064 };
1065 RTGETOPTSTATE GetState;
1066 RTGETOPTUNION ValueUnion;
1067 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1068 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1069
1070 Utf8Str strCompartmentId;
1071 Utf8Str strInstanceId;
1072 Utf8Str strDisplayName;
1073 Utf8Str strBucketName;
1074 Utf8Str strObjectName;
1075 com::SafeArray<BSTR> parameters;
1076
1077 int c;
1078 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1079 {
1080 switch (c)
1081 {
1082 case 'c':
1083 strCompartmentId=ValueUnion.psz;
1084 Bstr(Utf8Str("compartment-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1085 break;
1086 case 'i':
1087 strInstanceId=ValueUnion.psz;
1088 Bstr(Utf8Str("instance-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1089 break;
1090 case 'd':
1091 strDisplayName=ValueUnion.psz;
1092 Bstr(Utf8Str("display-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1093 break;
1094 case 'o':
1095 strObjectName=ValueUnion.psz;
1096 Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1097 break;
1098 case 'b':
1099 strBucketName=ValueUnion.psz;
1100 Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1101 break;
1102 case 'm':
1103 strBucketName=ValueUnion.psz;
1104 Bstr(Utf8Str("launch-mode=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1105 break;
1106 case VINF_GETOPT_NOT_OPTION:
1107 return errorUnknownSubcommand(ValueUnion.psz);
1108 default:
1109 return errorGetOpt(c, &ValueUnion);
1110 }
1111 }
1112
1113 if (strInstanceId.isNotEmpty() && strObjectName.isNotEmpty())
1114 return errorArgument("Conflicting parameters: --instance-id and --object-name can't be used together. Choose one.");
1115
1116 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1117
1118 ComObjPtr<ICloudClient> oCloudClient;
1119 CHECK_ERROR2_RET(hrc, pCloudProfile,
1120 CreateCloudClient(oCloudClient.asOutParam()),
1121 RTEXITCODE_FAILURE);
1122 if (strInstanceId.isNotEmpty())
1123 RTPrintf("Creating cloud image with name \'%s\' from the instance \'%s\'...\n",
1124 strDisplayName.c_str(), strInstanceId.c_str());
1125 else
1126 RTPrintf("Creating cloud image with name \'%s\' from the object \'%s\' in the bucket \'%s\'...\n",
1127 strDisplayName.c_str(), strObjectName.c_str(), strBucketName.c_str());
1128
1129 ComPtr<IProgress> progress;
1130 CHECK_ERROR2_RET(hrc, oCloudClient,
1131 CreateImage(ComSafeArrayAsInParam(parameters), progress.asOutParam()),
1132 RTEXITCODE_FAILURE);
1133 hrc = showProgress(progress);
1134 CHECK_PROGRESS_ERROR_RET(progress, ("Creating cloud image failed"), RTEXITCODE_FAILURE);
1135
1136 if (SUCCEEDED(hrc))
1137 RTPrintf("Cloud image was created successfully\n");
1138
1139 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1140}
1141
1142
1143static RTEXITCODE exportCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1144{
1145 HRESULT hrc = S_OK;
1146 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1147 if (FAILED(hrc))
1148 return RTEXITCODE_FAILURE;
1149
1150 static const RTGETOPTDEF s_aOptions[] =
1151 {
1152 { "--id", 'i', RTGETOPT_REQ_STRING },
1153 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
1154 { "--object-name", 'o', RTGETOPT_REQ_STRING },
1155 { "--display-name", 'd', RTGETOPT_REQ_STRING },
1156 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
1157 };
1158 RTGETOPTSTATE GetState;
1159 RTGETOPTUNION ValueUnion;
1160 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1161 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1162
1163 Utf8Str strImageId; /* XXX: this is vbox "image", i.e. medium */
1164 Utf8Str strBucketName;
1165 Utf8Str strObjectName;
1166 Utf8Str strDisplayName;
1167 Utf8Str strLaunchMode;
1168 com::SafeArray<BSTR> parameters;
1169
1170 int c;
1171 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1172 {
1173 switch (c)
1174 {
1175 case 'b': /* --bucket-name */
1176 {
1177 if (strBucketName.isNotEmpty())
1178 return errorArgument("Duplicate parameter: --bucket-name");
1179
1180 strBucketName = ValueUnion.psz;
1181 if (strBucketName.isEmpty())
1182 return errorArgument("Empty parameter: --bucket-name");
1183
1184 break;
1185 }
1186
1187 case 'o': /* --object-name */
1188 {
1189 if (strObjectName.isNotEmpty())
1190 return errorArgument("Duplicate parameter: --object-name");
1191
1192 strObjectName = ValueUnion.psz;
1193 if (strObjectName.isEmpty())
1194 return errorArgument("Empty parameter: --object-name");
1195
1196 break;
1197 }
1198
1199 case 'i': /* --id */
1200 {
1201 if (strImageId.isNotEmpty())
1202 return errorArgument("Duplicate parameter: --id");
1203
1204 strImageId = ValueUnion.psz;
1205 if (strImageId.isEmpty())
1206 return errorArgument("Empty parameter: --id");
1207
1208 break;
1209 }
1210
1211 case 'd': /* --display-name */
1212 {
1213 if (strDisplayName.isNotEmpty())
1214 return errorArgument("Duplicate parameter: --display-name");
1215
1216 strDisplayName = ValueUnion.psz;
1217 if (strDisplayName.isEmpty())
1218 return errorArgument("Empty parameter: --display-name");
1219
1220 break;
1221 }
1222
1223 case 'm': /* --launch-mode */
1224 {
1225 if (strLaunchMode.isNotEmpty())
1226 return errorArgument("Duplicate parameter: --launch-mode");
1227
1228 strLaunchMode = ValueUnion.psz;
1229 if (strLaunchMode.isEmpty())
1230 return errorArgument("Empty parameter: --launch-mode");
1231
1232 break;
1233 }
1234
1235 case VINF_GETOPT_NOT_OPTION:
1236 return errorUnknownSubcommand(ValueUnion.psz);
1237
1238 default:
1239 return errorGetOpt(c, &ValueUnion);
1240 }
1241 }
1242
1243 if (strImageId.isNotEmpty())
1244 BstrFmt("image-id=%s", strImageId.c_str()).detachTo(parameters.appendedRaw());
1245 else
1246 return errorArgument("Missing parameter: --id");
1247
1248 if (strBucketName.isNotEmpty())
1249 BstrFmt("bucket-name=%s", strBucketName.c_str()).detachTo(parameters.appendedRaw());
1250 else
1251 return errorArgument("Missing parameter: --bucket-name");
1252
1253 if (strObjectName.isNotEmpty())
1254 BstrFmt("object-name=%s", strObjectName.c_str()).detachTo(parameters.appendedRaw());
1255
1256 if (strDisplayName.isNotEmpty())
1257 BstrFmt("display-name=%s", strDisplayName.c_str()).detachTo(parameters.appendedRaw());
1258
1259 if (strLaunchMode.isNotEmpty())
1260 BstrFmt("launch-mode=%s", strLaunchMode.c_str()).detachTo(parameters.appendedRaw());
1261
1262
1263 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1264
1265 ComObjPtr<ICloudClient> oCloudClient;
1266 CHECK_ERROR2_RET(hrc, pCloudProfile,
1267 CreateCloudClient(oCloudClient.asOutParam()),
1268 RTEXITCODE_FAILURE);
1269
1270 if (strObjectName.isNotEmpty())
1271 RTPrintf("Exporting image \'%s\' to the Cloud with name \'%s\'...\n",
1272 strImageId.c_str(), strObjectName.c_str());
1273 else
1274 RTPrintf("Exporting image \'%s\' to the Cloud with default name\n",
1275 strImageId.c_str());
1276
1277 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
1278 SafeIfaceArray<IMedium> aImageList;
1279 CHECK_ERROR2_RET(hrc, pVirtualBox,
1280 COMGETTER(HardDisks)(ComSafeArrayAsOutParam(aImageList)),
1281 RTEXITCODE_FAILURE);
1282
1283 ComPtr<IMedium> pImage;
1284 size_t cImages = aImageList.size();
1285 bool fFound = false;
1286 for (size_t i = 0; i < cImages; ++i)
1287 {
1288 pImage = aImageList[i];
1289 Bstr bstrImageId;
1290 hrc = pImage->COMGETTER(Id)(bstrImageId.asOutParam());
1291 if (FAILED(hrc))
1292 continue;
1293
1294 com::Guid imageId(bstrImageId);
1295
1296 if (!imageId.isValid() || imageId.isZero())
1297 continue;
1298
1299 if (!strImageId.compare(imageId.toString()))
1300 {
1301 fFound = true;
1302 RTPrintf("Image %s was found\n", strImageId.c_str());
1303 break;
1304 }
1305 }
1306
1307 if (!fFound)
1308 {
1309 RTPrintf("Process of exporting the image to the Cloud was interrupted. The image wasn't found.\n");
1310 return RTEXITCODE_FAILURE;
1311 }
1312
1313 ComPtr<IProgress> progress;
1314 CHECK_ERROR2_RET(hrc, oCloudClient,
1315 ExportImage(pImage, ComSafeArrayAsInParam(parameters), progress.asOutParam()),
1316 RTEXITCODE_FAILURE);
1317 hrc = showProgress(progress);
1318 CHECK_PROGRESS_ERROR_RET(progress, ("Export the image to the Cloud failed"), RTEXITCODE_FAILURE);
1319
1320 if (SUCCEEDED(hrc))
1321 RTPrintf("Export the image to the Cloud was successfull\n");
1322
1323 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1324}
1325
1326static RTEXITCODE importCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1327{
1328 HRESULT hrc = S_OK;
1329 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1330 if (FAILED(hrc))
1331 return RTEXITCODE_FAILURE;
1332
1333 static const RTGETOPTDEF s_aOptions[] =
1334 {
1335 { "--id", 'i', RTGETOPT_REQ_STRING },
1336 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
1337 { "--object-name", 'o', RTGETOPT_REQ_STRING }
1338 };
1339 RTGETOPTSTATE GetState;
1340 RTGETOPTUNION ValueUnion;
1341 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1342 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1343
1344 Utf8Str strImageId;
1345 Utf8Str strCompartmentId;
1346 Utf8Str strBucketName;
1347 Utf8Str strObjectName;
1348 Utf8Str strDisplayName;
1349 com::SafeArray<BSTR> parameters;
1350
1351 int c;
1352 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1353 {
1354 switch (c)
1355 {
1356 case 'i':
1357 strImageId=ValueUnion.psz;
1358 break;
1359 case 'b':
1360 strBucketName=ValueUnion.psz;
1361 Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1362 break;
1363 case 'o':
1364 strObjectName=ValueUnion.psz;
1365 Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1366 break;
1367 case VINF_GETOPT_NOT_OPTION:
1368 return errorUnknownSubcommand(ValueUnion.psz);
1369 default:
1370 return errorGetOpt(c, &ValueUnion);
1371 }
1372 }
1373
1374 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1375
1376 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
1377 ComObjPtr<ICloudClient> oCloudClient;
1378 CHECK_ERROR2_RET(hrc, pCloudProfile,
1379 CreateCloudClient(oCloudClient.asOutParam()),
1380 RTEXITCODE_FAILURE);
1381 RTPrintf("Creating an object \'%s\' from the cloud image \'%s\'...\n", strObjectName.c_str(), strImageId.c_str());
1382
1383 ComPtr<IProgress> progress;
1384 CHECK_ERROR2_RET(hrc, oCloudClient,
1385 ImportImage(Bstr(strImageId).raw(), ComSafeArrayAsInParam(parameters), progress.asOutParam()),
1386 RTEXITCODE_FAILURE);
1387 hrc = showProgress(progress);
1388 CHECK_PROGRESS_ERROR_RET(progress, ("Cloud image import failed"), RTEXITCODE_FAILURE);
1389
1390 if (SUCCEEDED(hrc))
1391 {
1392 RTPrintf("Cloud image was imported successfully. Find the downloaded object with the name %s "
1393 "in the system temp folder (find the possible environment variables like TEMP, TMP and etc.)\n",
1394 strObjectName.c_str());
1395 }
1396
1397 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1398}
1399
1400static RTEXITCODE showCloudImageInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1401{
1402 HRESULT hrc = S_OK;
1403 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1404 if (FAILED(hrc))
1405 return RTEXITCODE_FAILURE;
1406
1407 static const RTGETOPTDEF s_aOptions[] =
1408 {
1409 { "--id", 'i', RTGETOPT_REQ_STRING }
1410 };
1411 RTGETOPTSTATE GetState;
1412 RTGETOPTUNION ValueUnion;
1413 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1414 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1415
1416 Utf8Str strImageId;
1417
1418 int c;
1419 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1420 {
1421 switch (c)
1422 {
1423 case 'i':
1424 strImageId = ValueUnion.psz;
1425 break;
1426 case VINF_GETOPT_NOT_OPTION:
1427 return errorUnknownSubcommand(ValueUnion.psz);
1428 default:
1429 return errorGetOpt(c, &ValueUnion);
1430 }
1431 }
1432
1433 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1434
1435 ComObjPtr<ICloudClient> oCloudClient;
1436 CHECK_ERROR2_RET(hrc, pCloudProfile,
1437 CreateCloudClient(oCloudClient.asOutParam()),
1438 RTEXITCODE_FAILURE);
1439 RTPrintf("Getting information about the cloud image with id \'%s\'...\n", strImageId.c_str());
1440
1441 ComPtr<IStringArray> infoArray;
1442 com::SafeArray<BSTR> pStrInfoArray;
1443 ComPtr<IProgress> pProgress;
1444
1445 RTPrintf("Reply is in the form \'image property\' = \'value\'\n");
1446 CHECK_ERROR2_RET(hrc, oCloudClient,
1447 GetImageInfo(Bstr(strImageId).raw(),
1448 infoArray.asOutParam(),
1449 pProgress.asOutParam()),
1450 RTEXITCODE_FAILURE);
1451
1452 hrc = showProgress(pProgress);
1453 CHECK_PROGRESS_ERROR_RET(pProgress, ("Getting information about the cloud image failed"), RTEXITCODE_FAILURE);
1454
1455 CHECK_ERROR2_RET(hrc,
1456 infoArray, COMGETTER(Values)(ComSafeArrayAsOutParam(pStrInfoArray)),
1457 RTEXITCODE_FAILURE);
1458
1459 RTPrintf("General information about the image:\n");
1460 size_t cParamNames = pStrInfoArray.size();
1461 for (size_t k = 0; k < cParamNames; k++)
1462 {
1463 Utf8Str data(pStrInfoArray[k]);
1464 RTPrintf("\t%s\n", data.c_str());
1465 }
1466
1467 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1468}
1469
1470static RTEXITCODE updateCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1471{
1472 RT_NOREF(a);
1473 RT_NOREF(iFirst);
1474 RT_NOREF(pCommonOpts);
1475 return RTEXITCODE_SUCCESS;
1476}
1477
1478static RTEXITCODE deleteCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1479{
1480 HRESULT hrc = S_OK;
1481 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1482 if (FAILED(hrc))
1483 return RTEXITCODE_FAILURE;
1484
1485 static const RTGETOPTDEF s_aOptions[] =
1486 {
1487 { "--id", 'i', RTGETOPT_REQ_STRING }
1488 };
1489 RTGETOPTSTATE GetState;
1490 RTGETOPTUNION ValueUnion;
1491 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1492 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1493
1494 Utf8Str strImageId;
1495
1496 int c;
1497 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1498 {
1499 switch (c)
1500 {
1501 case 'i':
1502 {
1503 if (strImageId.isNotEmpty())
1504 return errorArgument("Duplicate parameter: --id");
1505
1506 strImageId = ValueUnion.psz;
1507 if (strImageId.isEmpty())
1508 return errorArgument("Empty parameter: --id");
1509
1510 break;
1511 }
1512
1513 case VINF_GETOPT_NOT_OPTION:
1514 return errorUnknownSubcommand(ValueUnion.psz);
1515
1516 default:
1517 return errorGetOpt(c, &ValueUnion);
1518 }
1519 }
1520
1521 if (strImageId.isEmpty())
1522 return errorArgument("Missing parameter: --id");
1523
1524
1525 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1526
1527 ComObjPtr<ICloudClient> oCloudClient;
1528 CHECK_ERROR2_RET(hrc, pCloudProfile,
1529 CreateCloudClient(oCloudClient.asOutParam()),
1530 RTEXITCODE_FAILURE);
1531 RTPrintf("Deleting cloud image with id %s...\n", strImageId.c_str());
1532
1533 ComPtr<IProgress> progress;
1534 CHECK_ERROR2_RET(hrc, oCloudClient,
1535 DeleteImage(Bstr(strImageId).raw(), progress.asOutParam()),
1536 RTEXITCODE_FAILURE);
1537 hrc = showProgress(progress);
1538 CHECK_PROGRESS_ERROR_RET(progress, ("Deleting cloud image failed"), RTEXITCODE_FAILURE);
1539
1540 if (SUCCEEDED(hrc))
1541 RTPrintf("Cloud image with was deleted successfully\n");
1542
1543 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1544}
1545
1546static RTEXITCODE handleCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1547{
1548 if (a->argc < 1)
1549 return errorNoSubcommand();
1550
1551 static const RTGETOPTDEF s_aOptions[] =
1552 {
1553 { "create", 1000, RTGETOPT_REQ_NOTHING },
1554 { "export", 1001, RTGETOPT_REQ_NOTHING },
1555 { "import", 1002, RTGETOPT_REQ_NOTHING },
1556 { "info", 1003, RTGETOPT_REQ_NOTHING },
1557 { "update", 1004, RTGETOPT_REQ_NOTHING },
1558 { "delete", 1005, RTGETOPT_REQ_NOTHING }
1559 };
1560
1561 RTGETOPTSTATE GetState;
1562 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1563 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1564
1565 int c;
1566 RTGETOPTUNION ValueUnion;
1567 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1568 {
1569 switch (c)
1570 {
1571 /* Sub-commands: */
1572 case 1000:
1573// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_CREATE);
1574 return createCloudImage(a, GetState.iNext, pCommonOpts);
1575 case 1001:
1576// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_EXPORT);
1577 return exportCloudImage(a, GetState.iNext, pCommonOpts);
1578 case 1002:
1579// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_IMPORT);
1580 return importCloudImage(a, GetState.iNext, pCommonOpts);
1581 case 1003:
1582// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_INFO);
1583 return showCloudImageInfo(a, GetState.iNext, pCommonOpts);
1584 case 1004:
1585// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_UPDATE);
1586 return updateCloudImage(a, GetState.iNext, pCommonOpts);
1587 case 1005:
1588// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_DELETE);
1589 return deleteCloudImage(a, GetState.iNext, pCommonOpts);
1590 case VINF_GETOPT_NOT_OPTION:
1591 return errorUnknownSubcommand(ValueUnion.psz);
1592
1593 default:
1594 return errorGetOpt(c, &ValueUnion);
1595 }
1596 }
1597
1598 return errorNoSubcommand();
1599}
1600
1601RTEXITCODE handleCloud(HandlerArg *a)
1602{
1603 if (a->argc < 1)
1604 return errorNoSubcommand();
1605
1606 static const RTGETOPTDEF s_aOptions[] =
1607 {
1608 /* common options */
1609 { "--provider", 'v', RTGETOPT_REQ_STRING },
1610 { "--profile", 'f', RTGETOPT_REQ_STRING },
1611 { "list", 1000, RTGETOPT_REQ_NOTHING },
1612 { "image", 1001, RTGETOPT_REQ_NOTHING },
1613 { "instance", 1002, RTGETOPT_REQ_NOTHING },
1614 { "network", 1003, RTGETOPT_REQ_NOTHING },
1615 { "volume", 1004, RTGETOPT_REQ_NOTHING },
1616 { "object", 1005, RTGETOPT_REQ_NOTHING }
1617 };
1618
1619 RTGETOPTSTATE GetState;
1620 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
1621 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1622
1623 CLOUDCOMMONOPT commonOpts = { {NULL, NULL}, {NULL, NULL} };
1624 int c;
1625 RTGETOPTUNION ValueUnion;
1626 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1627 {
1628 switch (c)
1629 {
1630 case 'v': // --provider
1631 commonOpts.provider.pszProviderName = ValueUnion.psz;
1632 break;
1633 case 'f': // --profile
1634 commonOpts.profile.pszProfileName = ValueUnion.psz;
1635 break;
1636 /* Sub-commands: */
1637 case 1000:
1638 return handleCloudLists(a, GetState.iNext, &commonOpts);
1639 case 1001:
1640 return handleCloudImage(a, GetState.iNext, &commonOpts);
1641 case 1002:
1642 return handleCloudInstance(a, GetState.iNext, &commonOpts);
1643 case VINF_GETOPT_NOT_OPTION:
1644 return errorUnknownSubcommand(ValueUnion.psz);
1645
1646 default:
1647 return errorGetOpt(c, &ValueUnion);
1648 }
1649 }
1650
1651 return errorNoSubcommand();
1652}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use