VirtualBox

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

Last change on this file since 100651 was 99931, checked in by vboxsync, 19 months ago

Removed the character '\'.

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

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