VirtualBox

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

Last change on this file since 98298 was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 87.0 KB
Line 
1/* $Id: VBoxManageCloud.cpp 98103 2023-01-17 14:15:46Z 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 * General function which handles the "list" commands
443 *
444 * @returns RTEXITCODE
445 * @param a is the list of passed arguments
446 * @param iFirst is the position of the first unparsed argument in the arguments list
447 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
448 * arguments which have been already parsed before
449 */
450static RTEXITCODE handleCloudLists(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
451{
452 enum
453 {
454 kCloudListIota = 1000,
455 kCloudList_Images,
456 kCloudList_Instances,
457 kCloudList_Machines,
458 kCloudList_Networks,
459 kCloudList_Objects,
460 kCloudList_Subnets,
461 kCloudList_Vcns,
462 };
463
464 static const RTGETOPTDEF s_aOptions[] =
465 {
466 { "images", kCloudList_Images, RTGETOPT_REQ_NOTHING },
467 { "instances", kCloudList_Instances, RTGETOPT_REQ_NOTHING },
468 { "machines", kCloudList_Machines, RTGETOPT_REQ_NOTHING },
469 { "networks", kCloudList_Networks, RTGETOPT_REQ_NOTHING },
470 { "objects", kCloudList_Objects, RTGETOPT_REQ_NOTHING },
471 { "subnets", kCloudList_Subnets, RTGETOPT_REQ_NOTHING },
472 { "vcns", kCloudList_Vcns, RTGETOPT_REQ_NOTHING },
473 { "vms", kCloudList_Machines, RTGETOPT_REQ_NOTHING },
474
475 { "help", 'h', RTGETOPT_REQ_NOTHING },
476 { "-?", 'h', RTGETOPT_REQ_NOTHING },
477 { "-help", 'h', RTGETOPT_REQ_NOTHING },
478 { "--help", 'h', RTGETOPT_REQ_NOTHING },
479 };
480
481 if (a->argc == iFirst)
482 {
483 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
484 printHelp(g_pStdOut);
485 return RTEXITCODE_SUCCESS;
486 }
487
488 RTGETOPTSTATE GetState;
489 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
490 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
491
492 int c;
493 RTGETOPTUNION ValueUnion;
494 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
495 {
496 switch (c)
497 {
498 case kCloudList_Images:
499 setCurrentSubcommand(HELP_SCOPE_CLOUDLIST_IMAGES);
500 return listCloudImages(a, GetState.iNext, pCommonOpts);
501
502 case kCloudList_Instances:
503 setCurrentSubcommand(HELP_SCOPE_CLOUDLIST_INSTANCES);
504 return listCloudInstances(a, GetState.iNext, pCommonOpts);
505
506 case kCloudList_Machines:
507 return listCloudMachines(a, GetState.iNext,
508 pCommonOpts->provider.pszProviderName,
509 pCommonOpts->profile.pszProfileName);
510
511 case 'h':
512 printHelp(g_pStdOut);
513 return RTEXITCODE_SUCCESS;
514
515 case VINF_GETOPT_NOT_OPTION:
516 return errorUnknownSubcommand(ValueUnion.psz);
517
518 default:
519 return errorGetOpt(c, &ValueUnion);
520 }
521 }
522
523 return errorNoSubcommand();
524}
525
526static RTEXITCODE createCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
527{
528 HRESULT hrc = S_OK;
529
530 enum
531 {
532 kInstanceIota = 1000,
533 kInstance_ShapeCpu,
534 kInstance_ShapeMemory,
535 };
536
537 static const RTGETOPTDEF s_aOptions[] =
538 {
539 { "--image-id", 'i', RTGETOPT_REQ_STRING },
540 { "--boot-volume-id", 'v', RTGETOPT_REQ_STRING },
541 { "--display-name", 'n', RTGETOPT_REQ_STRING },
542 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
543 { "--shape", 's', RTGETOPT_REQ_STRING },
544 { "--shape-cpus", kInstance_ShapeCpu, RTGETOPT_REQ_UINT32 },
545 { "--shape-memory", kInstance_ShapeMemory, RTGETOPT_REQ_UINT32 },
546 { "--domain-name", 'd', RTGETOPT_REQ_STRING },
547 { "--boot-disk-size", 'b', RTGETOPT_REQ_STRING },
548 { "--publicip", 'p', RTGETOPT_REQ_STRING },
549 { "--subnet", 't', RTGETOPT_REQ_STRING },
550 { "--privateip", 'P', RTGETOPT_REQ_STRING },
551 { "--launch", 'l', RTGETOPT_REQ_STRING },
552 { "--public-ssh-key", 'k', RTGETOPT_REQ_STRING },
553 { "--cloud-init-script-path", 'c', RTGETOPT_REQ_STRING },
554 { "help", 'h', RTGETOPT_REQ_NOTHING },
555 { "--help", 'h', RTGETOPT_REQ_NOTHING }
556 };
557 RTGETOPTSTATE GetState;
558 RTGETOPTUNION ValueUnion;
559 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
560 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
561 if (a->argc == iFirst)
562 {
563 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
564 printHelp(g_pStdOut);
565 return RTEXITCODE_SUCCESS;
566 }
567
568 ComPtr<IAppliance> pAppliance;
569 CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE);
570 ULONG vsdNum = 1;
571 CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(1, &vsdNum), RTEXITCODE_FAILURE);
572 com::SafeIfaceArray<IVirtualSystemDescription> virtualSystemDescriptions;
573 CHECK_ERROR2_RET(hrc, pAppliance,
574 COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(virtualSystemDescriptions)),
575 RTEXITCODE_FAILURE);
576 ComPtr<IVirtualSystemDescription> pVSD = virtualSystemDescriptions[0];
577
578 Utf8Str strDisplayName, strImageId, strBootVolumeId, strPublicSSHKey;
579 int c;
580 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
581 {
582 switch (c)
583 {
584 case 'i':
585 strImageId = ValueUnion.psz;
586 pVSD->AddDescription(VirtualSystemDescriptionType_CloudImageId,
587 Bstr(ValueUnion.psz).raw(), NULL);
588 break;
589
590 case 'v':
591 strBootVolumeId = ValueUnion.psz;
592 pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootVolumeId,
593 Bstr(ValueUnion.psz).raw(), NULL);
594 break;
595 case 'n':
596 strDisplayName = ValueUnion.psz;
597 pVSD->AddDescription(VirtualSystemDescriptionType_Name,
598 Bstr(ValueUnion.psz).raw(), NULL);
599 break;
600 case 'm':
601 pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCILaunchMode,
602 Bstr(ValueUnion.psz).raw(), NULL);
603 break;
604
605 case 's':
606 pVSD->AddDescription(VirtualSystemDescriptionType_CloudInstanceShape,
607 Bstr(ValueUnion.psz).raw(), NULL);
608 break;
609
610 case kInstance_ShapeCpu:
611 pVSD->AddDescription(VirtualSystemDescriptionType_CloudShapeCpus,
612 BstrFmt("%RI32", ValueUnion.u32).raw(), NULL);
613 break;
614
615 case kInstance_ShapeMemory:
616 pVSD->AddDescription(VirtualSystemDescriptionType_CloudShapeMemory,
617 BstrFmt("%RI32", ValueUnion.u32).raw(), NULL);
618 break;
619
620 case 'd':
621 pVSD->AddDescription(VirtualSystemDescriptionType_CloudDomain,
622 Bstr(ValueUnion.psz).raw(), NULL);
623 break;
624 case 'b':
625 pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootDiskSize,
626 Bstr(ValueUnion.psz).raw(), NULL);
627 break;
628 case 'p':
629 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicIP,
630 Bstr(ValueUnion.psz).raw(), NULL);
631 break;
632 case 'P':
633 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPrivateIP,
634 Bstr(ValueUnion.psz).raw(), NULL);
635 break;
636 case 't':
637 pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCISubnet,
638 Bstr(ValueUnion.psz).raw(), NULL);
639 break;
640 case 'l':
641 {
642 Utf8Str strLaunch(ValueUnion.psz);
643 if (strLaunch.isNotEmpty() && (strLaunch.equalsIgnoreCase("true") || strLaunch.equalsIgnoreCase("false")))
644 pVSD->AddDescription(VirtualSystemDescriptionType_CloudLaunchInstance,
645 Bstr(ValueUnion.psz).raw(), NULL);
646 break;
647 }
648 case 'k':
649 strPublicSSHKey = ValueUnion.psz;
650 pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicSSHKey,
651 Bstr(ValueUnion.psz).raw(), NULL);
652 break;
653 case 'c':
654 pVSD->AddDescription(VirtualSystemDescriptionType_CloudInitScriptPath,
655 Bstr(ValueUnion.psz).raw(), NULL);
656 break;
657 case 'h':
658 printHelp(g_pStdOut);
659 return RTEXITCODE_SUCCESS;
660 case VINF_GETOPT_NOT_OPTION:
661 return errorUnknownSubcommand(ValueUnion.psz);
662 default:
663 return errorGetOpt(c, &ValueUnion);
664 }
665 }
666
667 /* Delayed check. It allows us to print help information.*/
668 hrc = checkAndSetCommonOptions(a, pCommonOpts);
669 if (FAILED(hrc))
670 return RTEXITCODE_FAILURE;
671
672 if (strPublicSSHKey.isEmpty())
673 RTPrintf(Cloud::tr("Warning!!! Public SSH key doesn't present in the passed arguments...\n"));
674
675 if (strImageId.isNotEmpty() && strBootVolumeId.isNotEmpty())
676 return errorArgument(Cloud::tr("Parameters --image-id and --boot-volume-id are mutually exclusive. "
677 "Only one of them must be presented."));
678
679 if (strImageId.isEmpty() && strBootVolumeId.isEmpty())
680 return errorArgument(Cloud::tr("Missing parameter --image-id or --boot-volume-id. One of them must be presented."));
681
682 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
683
684 pVSD->AddDescription(VirtualSystemDescriptionType_CloudProfileName,
685 Bstr(pCommonOpts->profile.pszProfileName).raw(),
686 NULL);
687
688 ComObjPtr<ICloudClient> oCloudClient;
689 CHECK_ERROR2_RET(hrc, pCloudProfile,
690 CreateCloudClient(oCloudClient.asOutParam()),
691 RTEXITCODE_FAILURE);
692
693 ComPtr<IStringArray> infoArray;
694 com::SafeArray<BSTR> pStrInfoArray;
695 ComPtr<IProgress> pProgress;
696
697#if 0
698 /*
699 * OCI API returns an error during an instance creation if the image isn't available
700 * or in the inappropriate state. So the check can be omitted.
701 */
702 RTPrintf(Cloud::tr("Checking the cloud image with id \'%s\'...\n"), strImageId.c_str());
703 CHECK_ERROR2_RET(hrc, oCloudClient,
704 GetImageInfo(Bstr(strImageId).raw(),
705 infoArray.asOutParam(),
706 pProgress.asOutParam()),
707 RTEXITCODE_FAILURE);
708
709 hrc = showProgress(pProgress);
710 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Checking the cloud image failed")), RTEXITCODE_FAILURE);
711
712 pProgress.setNull();
713#endif
714
715 if (strImageId.isNotEmpty())
716 RTPrintf(Cloud::tr("Creating cloud instance with name \'%s\' from the image \'%s\'...\n"),
717 strDisplayName.c_str(), strImageId.c_str());
718 else
719 RTPrintf(Cloud::tr("Creating cloud instance with name \'%s\' from the boot volume \'%s\'...\n"),
720 strDisplayName.c_str(), strBootVolumeId.c_str());
721
722 CHECK_ERROR2_RET(hrc, oCloudClient, LaunchVM(pVSD, pProgress.asOutParam()), RTEXITCODE_FAILURE);
723
724 hrc = showProgress(pProgress);
725 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Creating cloud instance failed")), RTEXITCODE_FAILURE);
726
727 if (SUCCEEDED(hrc))
728 RTPrintf(Cloud::tr("Cloud instance was created successfully\n"));
729
730 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
731}
732
733static RTEXITCODE updateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
734{
735 RT_NOREF(a);
736 RT_NOREF(iFirst);
737 RT_NOREF(pCommonOpts);
738 return RTEXITCODE_SUCCESS;
739}
740
741static RTEXITCODE showCloudInstanceInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
742{
743 HRESULT hrc = S_OK;
744
745 static const RTGETOPTDEF s_aOptions[] =
746 {
747 { "--id", 'i', RTGETOPT_REQ_STRING },
748 { "help", 'h', RTGETOPT_REQ_NOTHING },
749 { "--help", 'h', RTGETOPT_REQ_NOTHING }
750 };
751 RTGETOPTSTATE GetState;
752 RTGETOPTUNION ValueUnion;
753 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
754 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
755 if (a->argc == iFirst)
756 {
757 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
758 printHelp(g_pStdOut);
759 return RTEXITCODE_SUCCESS;
760 }
761
762 Utf8Str strInstanceId;
763
764 int c;
765 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
766 {
767 switch (c)
768 {
769 case 'i':
770 {
771 if (strInstanceId.isNotEmpty())
772 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
773
774 strInstanceId = ValueUnion.psz;
775 if (strInstanceId.isEmpty())
776 return errorArgument(Cloud::tr("Empty parameter: --id"));
777
778 break;
779 }
780 case 'h':
781 printHelp(g_pStdOut);
782 return RTEXITCODE_SUCCESS;
783 case VINF_GETOPT_NOT_OPTION:
784 return errorUnknownSubcommand(ValueUnion.psz);
785
786 default:
787 return errorGetOpt(c, &ValueUnion);
788 }
789 }
790
791 /* Delayed check. It allows us to print help information.*/
792 hrc = checkAndSetCommonOptions(a, pCommonOpts);
793 if (FAILED(hrc))
794 return RTEXITCODE_FAILURE;
795
796 if (strInstanceId.isEmpty())
797 return errorArgument(Cloud::tr("Missing parameter: --id"));
798
799 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
800
801 ComObjPtr<ICloudClient> oCloudClient;
802 CHECK_ERROR2_RET(hrc, pCloudProfile,
803 CreateCloudClient(oCloudClient.asOutParam()),
804 RTEXITCODE_FAILURE);
805 RTPrintf(Cloud::tr("Getting information about cloud instance with id %s...\n"), strInstanceId.c_str());
806 RTPrintf(Cloud::tr("Reply is in the form \'setting name\' = \'value\'\n"));
807
808 ComPtr<IAppliance> pAppliance;
809 CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE);
810
811 com::SafeIfaceArray<IVirtualSystemDescription> vsdArray;
812 ULONG requestedVSDnums = 1;
813 ULONG newVSDnums = 0;
814 CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(requestedVSDnums, &newVSDnums), RTEXITCODE_FAILURE);
815 if (requestedVSDnums != newVSDnums)
816 return RTEXITCODE_FAILURE;
817
818 CHECK_ERROR2_RET(hrc, pAppliance, COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(vsdArray)), RTEXITCODE_FAILURE);
819 ComPtr<IVirtualSystemDescription> instanceDescription = vsdArray[0];
820
821 ComPtr<IProgress> progress;
822 CHECK_ERROR2_RET(hrc, oCloudClient,
823 GetInstanceInfo(Bstr(strInstanceId).raw(), instanceDescription, progress.asOutParam()),
824 RTEXITCODE_FAILURE);
825
826 hrc = showProgress(progress);
827 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Getting information about cloud instance failed")), RTEXITCODE_FAILURE);
828
829 RTPrintf(Cloud::tr("Cloud instance info (provider '%s'):\n"),
830 pCommonOpts->provider.pszProviderName);
831
832 struct vsdHReadable {
833 VirtualSystemDescriptionType_T vsdType;
834 Utf8Str strFound;
835 Utf8Str strNotFound;
836 };
837
838 const size_t vsdHReadableArraySize = 13;//the number of items in the vsdHReadableArray
839 vsdHReadable vsdHReadableArray[vsdHReadableArraySize] = {
840 {VirtualSystemDescriptionType_CloudDomain, Cloud::tr("Availability domain = %ls\n"), Cloud::tr("Availability domain wasn't found\n")},
841 {VirtualSystemDescriptionType_Name, Cloud::tr("Instance displayed name = %ls\n"), Cloud::tr("Instance displayed name wasn't found\n")},
842 {VirtualSystemDescriptionType_CloudInstanceState, Cloud::tr("Instance state = %ls\n"), Cloud::tr("Instance state wasn't found\n")},
843 {VirtualSystemDescriptionType_CloudInstanceId, Cloud::tr("Instance Id = %ls\n"), Cloud::tr("Instance Id wasn't found\n")},
844 {VirtualSystemDescriptionType_CloudInstanceDisplayName, Cloud::tr("Instance name = %ls\n"), Cloud::tr("Instance name wasn't found\n")},
845 {VirtualSystemDescriptionType_CloudImageId, Cloud::tr("Bootable image Id = %ls\n"),
846 Cloud::tr("Image Id whom the instance is booted up wasn't found\n")},
847 {VirtualSystemDescriptionType_CloudInstanceShape, Cloud::tr("Shape of the instance = %ls\n"),
848 Cloud::tr("The shape of the instance wasn't found\n")},
849 {VirtualSystemDescriptionType_OS, Cloud::tr("Type of guest OS = %ls\n"), Cloud::tr("Type of guest OS wasn't found\n")},
850 {VirtualSystemDescriptionType_Memory, Cloud::tr("RAM = %ls MB\n"), Cloud::tr("Value for RAM wasn't found\n")},
851 {VirtualSystemDescriptionType_CPU, Cloud::tr("CPUs = %ls\n"), Cloud::tr("Numbers of CPUs weren't found\n")},
852 {VirtualSystemDescriptionType_CloudPublicIP, Cloud::tr("Instance public IP = %ls\n"), Cloud::tr("Public IP wasn't found\n")},
853 {VirtualSystemDescriptionType_Miscellaneous, "%ls\n", Cloud::tr("Free-form tags or metadata weren't found\n")},
854 {VirtualSystemDescriptionType_CloudInitScriptPath, "%ls\n", Cloud::tr("Cloud-init script wasn't found\n")}
855 };
856
857 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
858 com::SafeArray<BSTR> aRefs;
859 com::SafeArray<BSTR> aOvfValues;
860 com::SafeArray<BSTR> aVBoxValues;
861 com::SafeArray<BSTR> aExtraConfigValues;
862
863 for (size_t i=0; i<vsdHReadableArraySize ; ++i)
864 {
865 hrc = instanceDescription->GetDescriptionByType(vsdHReadableArray[i].vsdType,
866 ComSafeArrayAsOutParam(retTypes),
867 ComSafeArrayAsOutParam(aRefs),
868 ComSafeArrayAsOutParam(aOvfValues),
869 ComSafeArrayAsOutParam(aVBoxValues),
870 ComSafeArrayAsOutParam(aExtraConfigValues));
871 if (FAILED(hrc) || aVBoxValues.size() == 0)
872 LogRel((vsdHReadableArray[i].strNotFound.c_str()));
873 else
874 {
875 LogRel(("Size is %d", aVBoxValues.size()));
876 for (size_t j = 0; j<aVBoxValues.size(); ++j)
877 {
878 RTPrintf(vsdHReadableArray[i].strFound.c_str(), aVBoxValues[j]);
879 }
880 }
881
882 retTypes.setNull();
883 aRefs.setNull();
884 aOvfValues.setNull();
885 aVBoxValues.setNull();
886 aExtraConfigValues.setNull();
887 }
888
889 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
890}
891
892static RTEXITCODE startCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
893{
894 HRESULT hrc = S_OK;
895
896 static const RTGETOPTDEF s_aOptions[] =
897 {
898 { "--id", 'i', RTGETOPT_REQ_STRING },
899 { "help", 'h', RTGETOPT_REQ_NOTHING },
900 { "--help", 'h', RTGETOPT_REQ_NOTHING }
901 };
902 RTGETOPTSTATE GetState;
903 RTGETOPTUNION ValueUnion;
904 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
905 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
906 if (a->argc == iFirst)
907 {
908 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
909 printHelp(g_pStdOut);
910 return RTEXITCODE_SUCCESS;
911 }
912
913 Utf8Str strInstanceId;
914
915 int c;
916 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
917 {
918 switch (c)
919 {
920 case 'i':
921 {
922 if (strInstanceId.isNotEmpty())
923 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
924
925 strInstanceId = ValueUnion.psz;
926 if (strInstanceId.isEmpty())
927 return errorArgument(Cloud::tr("Empty parameter: --id"));
928
929 break;
930 }
931 case 'h':
932 printHelp(g_pStdOut);
933 return RTEXITCODE_SUCCESS;
934 case VINF_GETOPT_NOT_OPTION:
935 return errorUnknownSubcommand(ValueUnion.psz);
936
937 default:
938 return errorGetOpt(c, &ValueUnion);
939 }
940 }
941
942 /* Delayed check. It allows us to print help information.*/
943 hrc = checkAndSetCommonOptions(a, pCommonOpts);
944 if (FAILED(hrc))
945 return RTEXITCODE_FAILURE;
946
947 if (strInstanceId.isEmpty())
948 return errorArgument(Cloud::tr("Missing parameter: --id"));
949
950 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
951
952 ComObjPtr<ICloudClient> oCloudClient;
953 CHECK_ERROR2_RET(hrc, pCloudProfile,
954 CreateCloudClient(oCloudClient.asOutParam()),
955 RTEXITCODE_FAILURE);
956 RTPrintf(Cloud::tr("Starting cloud instance with id %s...\n"), strInstanceId.c_str());
957
958 ComPtr<IProgress> progress;
959 CHECK_ERROR2_RET(hrc, oCloudClient,
960 StartInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
961 RTEXITCODE_FAILURE);
962 hrc = showProgress(progress);
963 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Starting the cloud instance failed")), RTEXITCODE_FAILURE);
964
965 if (SUCCEEDED(hrc))
966 RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was started\n"),
967 strInstanceId.c_str(),
968 pCommonOpts->provider.pszProviderName,
969 pCommonOpts->profile.pszProfileName);
970
971 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
972}
973
974static RTEXITCODE pauseCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
975{
976 HRESULT hrc = S_OK;
977
978 static const RTGETOPTDEF s_aOptions[] =
979 {
980 { "--id", 'i', RTGETOPT_REQ_STRING },
981 { "help", 'h', RTGETOPT_REQ_NOTHING },
982 { "--help", 'h', RTGETOPT_REQ_NOTHING }
983 };
984 RTGETOPTSTATE GetState;
985 RTGETOPTUNION ValueUnion;
986 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
987 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
988 if (a->argc == iFirst)
989 {
990 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
991 printHelp(g_pStdOut);
992 return RTEXITCODE_SUCCESS;
993 }
994
995 Utf8Str strInstanceId;
996
997 int c;
998 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
999 {
1000 switch (c)
1001 {
1002 case 'i':
1003 {
1004 if (strInstanceId.isNotEmpty())
1005 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
1006
1007 strInstanceId = ValueUnion.psz;
1008 if (strInstanceId.isEmpty())
1009 return errorArgument(Cloud::tr("Empty parameter: --id"));
1010
1011 break;
1012 }
1013 case 'h':
1014 printHelp(g_pStdOut);
1015 return RTEXITCODE_SUCCESS;
1016 case VINF_GETOPT_NOT_OPTION:
1017 return errorUnknownSubcommand(ValueUnion.psz);
1018
1019 default:
1020 return errorGetOpt(c, &ValueUnion);
1021 }
1022 }
1023
1024 /* Delayed check. It allows us to print help information.*/
1025 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1026 if (FAILED(hrc))
1027 return RTEXITCODE_FAILURE;
1028
1029 if (strInstanceId.isEmpty())
1030 return errorArgument(Cloud::tr("Missing parameter: --id"));
1031
1032 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1033
1034 ComObjPtr<ICloudClient> oCloudClient;
1035 CHECK_ERROR2_RET(hrc, pCloudProfile,
1036 CreateCloudClient(oCloudClient.asOutParam()),
1037 RTEXITCODE_FAILURE);
1038 RTPrintf(Cloud::tr("Pausing cloud instance with id %s...\n"), strInstanceId.c_str());
1039
1040 ComPtr<IProgress> progress;
1041 CHECK_ERROR2_RET(hrc, oCloudClient,
1042 PauseInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
1043 RTEXITCODE_FAILURE);
1044 hrc = showProgress(progress);
1045 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Pause the cloud instance failed")), RTEXITCODE_FAILURE);
1046
1047 if (SUCCEEDED(hrc))
1048 RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was paused\n"),
1049 strInstanceId.c_str(),
1050 pCommonOpts->provider.pszProviderName,
1051 pCommonOpts->profile.pszProfileName);
1052
1053 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1054}
1055
1056static RTEXITCODE terminateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1057{
1058 HRESULT hrc = S_OK;
1059
1060 static const RTGETOPTDEF s_aOptions[] =
1061 {
1062 { "--id", 'i', RTGETOPT_REQ_STRING },
1063 { "help", 'h', RTGETOPT_REQ_NOTHING },
1064 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1065 };
1066 RTGETOPTSTATE GetState;
1067 RTGETOPTUNION ValueUnion;
1068 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1069 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1070 if (a->argc == iFirst)
1071 {
1072 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1073 printHelp(g_pStdOut);
1074 return RTEXITCODE_SUCCESS;
1075 }
1076
1077 Utf8Str strInstanceId;
1078
1079 int c;
1080 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1081 {
1082 switch (c)
1083 {
1084 case 'i':
1085 {
1086 if (strInstanceId.isNotEmpty())
1087 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
1088
1089 strInstanceId = ValueUnion.psz;
1090 if (strInstanceId.isEmpty())
1091 return errorArgument(Cloud::tr("Empty parameter: --id"));
1092
1093 break;
1094 }
1095 case 'h':
1096 printHelp(g_pStdOut);
1097 return RTEXITCODE_SUCCESS;
1098 case VINF_GETOPT_NOT_OPTION:
1099 return errorUnknownSubcommand(ValueUnion.psz);
1100
1101 default:
1102 return errorGetOpt(c, &ValueUnion);
1103 }
1104 }
1105
1106 /* Delayed check. It allows us to print help information.*/
1107 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1108 if (FAILED(hrc))
1109 return RTEXITCODE_FAILURE;
1110
1111 if (strInstanceId.isEmpty())
1112 return errorArgument(Cloud::tr("Missing parameter: --id"));
1113
1114
1115 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1116
1117 ComObjPtr<ICloudClient> oCloudClient;
1118 CHECK_ERROR2_RET(hrc, pCloudProfile,
1119 CreateCloudClient(oCloudClient.asOutParam()),
1120 RTEXITCODE_FAILURE);
1121 RTPrintf(Cloud::tr("Terminating cloud instance with id %s...\n"), strInstanceId.c_str());
1122
1123 ComPtr<IProgress> progress;
1124 CHECK_ERROR2_RET(hrc, oCloudClient,
1125 TerminateInstance(Bstr(strInstanceId).raw(), progress.asOutParam()),
1126 RTEXITCODE_FAILURE);
1127 hrc = showProgress(progress);
1128 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Termination the cloud instance failed")), RTEXITCODE_FAILURE);
1129
1130 if (SUCCEEDED(hrc))
1131 RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was terminated\n"),
1132 strInstanceId.c_str(),
1133 pCommonOpts->provider.pszProviderName,
1134 pCommonOpts->profile.pszProfileName);
1135
1136 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1137}
1138
1139static RTEXITCODE handleCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1140{
1141 enum
1142 {
1143 kCloudInstanceIota = 1000,
1144 kCloudInstance_Create,
1145 kCloudInstance_Info,
1146 kCloudInstance_Pause,
1147 kCloudInstance_Start,
1148 kCloudInstance_Terminate,
1149 kCloudInstance_Update,
1150 };
1151
1152 static const RTGETOPTDEF s_aOptions[] =
1153 {
1154 { "create", kCloudInstance_Create, RTGETOPT_REQ_NOTHING },
1155 { "info", kCloudInstance_Info, RTGETOPT_REQ_NOTHING },
1156 { "pause", kCloudInstance_Pause, RTGETOPT_REQ_NOTHING },
1157 { "start", kCloudInstance_Start, RTGETOPT_REQ_NOTHING },
1158 { "terminate", kCloudInstance_Terminate, RTGETOPT_REQ_NOTHING },
1159 { "update", kCloudInstance_Update, RTGETOPT_REQ_NOTHING },
1160
1161 { "help", 'h', RTGETOPT_REQ_NOTHING },
1162 { "-?", 'h', RTGETOPT_REQ_NOTHING },
1163 { "-help", 'h', RTGETOPT_REQ_NOTHING },
1164 { "--help", 'h', RTGETOPT_REQ_NOTHING },
1165 };
1166
1167 if (a->argc == iFirst)
1168 {
1169 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1170 printHelp(g_pStdOut);
1171 return RTEXITCODE_SUCCESS;
1172 }
1173
1174 RTGETOPTSTATE GetState;
1175 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1176 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1177
1178 int c;
1179 RTGETOPTUNION ValueUnion;
1180 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1181 {
1182 switch (c)
1183 {
1184 /* Sub-commands: */
1185 case kCloudInstance_Create:
1186 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_CREATE);
1187 return createCloudInstance(a, GetState.iNext, pCommonOpts);
1188
1189 case kCloudInstance_Start:
1190 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_START);
1191 return startCloudInstance(a, GetState.iNext, pCommonOpts);
1192
1193 case kCloudInstance_Pause:
1194 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_PAUSE);
1195 return pauseCloudInstance(a, GetState.iNext, pCommonOpts);
1196
1197 case kCloudInstance_Info:
1198 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_INFO);
1199 return showCloudInstanceInfo(a, GetState.iNext, pCommonOpts);
1200
1201 case kCloudInstance_Update:
1202// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_UPDATE);
1203 return updateCloudInstance(a, GetState.iNext, pCommonOpts);
1204
1205 case kCloudInstance_Terminate:
1206 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_TERMINATE);
1207 return terminateCloudInstance(a, GetState.iNext, pCommonOpts);
1208
1209 case 'h':
1210 printHelp(g_pStdOut);
1211 return RTEXITCODE_SUCCESS;
1212
1213 case VINF_GETOPT_NOT_OPTION:
1214 return errorUnknownSubcommand(ValueUnion.psz);
1215
1216 default:
1217 return errorGetOpt(c, &ValueUnion);
1218 }
1219 }
1220
1221 return errorNoSubcommand();
1222}
1223
1224
1225static RTEXITCODE createCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1226{
1227 HRESULT hrc = S_OK;
1228
1229 static const RTGETOPTDEF s_aOptions[] =
1230 {
1231 { "--object-name", 'o', RTGETOPT_REQ_STRING },
1232 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
1233 { "--compartment-id", 'c', RTGETOPT_REQ_STRING },
1234 { "--instance-id", 'i', RTGETOPT_REQ_STRING },
1235 { "--display-name", 'd', RTGETOPT_REQ_STRING },
1236 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
1237 { "help", 'h', RTGETOPT_REQ_NOTHING },
1238 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1239 };
1240 RTGETOPTSTATE GetState;
1241 RTGETOPTUNION ValueUnion;
1242 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1243 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1244 if (a->argc == iFirst)
1245 {
1246 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1247 printHelp(g_pStdOut);
1248 return RTEXITCODE_SUCCESS;
1249 }
1250
1251 Utf8Str strCompartmentId;
1252 Utf8Str strInstanceId;
1253 Utf8Str strDisplayName;
1254 Utf8Str strBucketName;
1255 Utf8Str strObjectName;
1256 com::SafeArray<BSTR> parameters;
1257
1258 int c;
1259 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1260 {
1261 switch (c)
1262 {
1263 case 'c':
1264 strCompartmentId=ValueUnion.psz;
1265 Bstr(Utf8Str("compartment-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1266 break;
1267 case 'i':
1268 strInstanceId=ValueUnion.psz;
1269 Bstr(Utf8Str("instance-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1270 break;
1271 case 'd':
1272 strDisplayName=ValueUnion.psz;
1273 Bstr(Utf8Str("display-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1274 break;
1275 case 'o':
1276 strObjectName=ValueUnion.psz;
1277 Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1278 break;
1279 case 'b':
1280 strBucketName=ValueUnion.psz;
1281 Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1282 break;
1283 case 'm':
1284 strBucketName=ValueUnion.psz;
1285 Bstr(Utf8Str("launch-mode=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1286 break;
1287 case 'h':
1288 printHelp(g_pStdOut);
1289 return RTEXITCODE_SUCCESS;
1290 case VINF_GETOPT_NOT_OPTION:
1291 return errorUnknownSubcommand(ValueUnion.psz);
1292 default:
1293 return errorGetOpt(c, &ValueUnion);
1294 }
1295 }
1296
1297 /* Delayed check. It allows us to print help information.*/
1298 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1299 if (FAILED(hrc))
1300 return RTEXITCODE_FAILURE;
1301
1302 if (strInstanceId.isNotEmpty() && strObjectName.isNotEmpty())
1303 return errorArgument(Cloud::tr("Conflicting parameters: --instance-id and --object-name can't be used together. Choose one."));
1304
1305 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1306
1307 ComObjPtr<ICloudClient> oCloudClient;
1308 CHECK_ERROR2_RET(hrc, pCloudProfile,
1309 CreateCloudClient(oCloudClient.asOutParam()),
1310 RTEXITCODE_FAILURE);
1311 if (strInstanceId.isNotEmpty())
1312 RTPrintf(Cloud::tr("Creating cloud image with name \'%s\' from the instance \'%s\'...\n"),
1313 strDisplayName.c_str(), strInstanceId.c_str());
1314 else
1315 RTPrintf(Cloud::tr("Creating cloud image with name \'%s\' from the object \'%s\' in the bucket \'%s\'...\n"),
1316 strDisplayName.c_str(), strObjectName.c_str(), strBucketName.c_str());
1317
1318 ComPtr<IProgress> progress;
1319 CHECK_ERROR2_RET(hrc, oCloudClient,
1320 CreateImage(ComSafeArrayAsInParam(parameters), progress.asOutParam()),
1321 RTEXITCODE_FAILURE);
1322 hrc = showProgress(progress);
1323 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Creating cloud image failed")), RTEXITCODE_FAILURE);
1324
1325 if (SUCCEEDED(hrc))
1326 RTPrintf(Cloud::tr("Cloud image was created successfully\n"));
1327
1328 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1329}
1330
1331
1332static RTEXITCODE exportCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1333{
1334 HRESULT hrc = S_OK;
1335
1336 static const RTGETOPTDEF s_aOptions[] =
1337 {
1338 { "--id", 'i', RTGETOPT_REQ_STRING },
1339 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
1340 { "--object-name", 'o', RTGETOPT_REQ_STRING },
1341 { "--display-name", 'd', RTGETOPT_REQ_STRING },
1342 { "--launch-mode", 'm', RTGETOPT_REQ_STRING },
1343 { "help", 'h', RTGETOPT_REQ_NOTHING },
1344 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1345 };
1346 RTGETOPTSTATE GetState;
1347 RTGETOPTUNION ValueUnion;
1348 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1349 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1350 if (a->argc == iFirst)
1351 {
1352 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1353 printHelp(g_pStdOut);
1354 return RTEXITCODE_SUCCESS;
1355 }
1356
1357 Utf8Str strImageId; /* XXX: this is vbox "image", i.e. medium */
1358 Utf8Str strBucketName;
1359 Utf8Str strObjectName;
1360 Utf8Str strDisplayName;
1361 Utf8Str strLaunchMode;
1362 com::SafeArray<BSTR> parameters;
1363
1364 int c;
1365 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1366 {
1367 switch (c)
1368 {
1369 case 'b': /* --bucket-name */
1370 {
1371 if (strBucketName.isNotEmpty())
1372 return errorArgument(Cloud::tr("Duplicate parameter: --bucket-name"));
1373
1374 strBucketName = ValueUnion.psz;
1375 if (strBucketName.isEmpty())
1376 return errorArgument(Cloud::tr("Empty parameter: --bucket-name"));
1377
1378 break;
1379 }
1380
1381 case 'o': /* --object-name */
1382 {
1383 if (strObjectName.isNotEmpty())
1384 return errorArgument(Cloud::tr("Duplicate parameter: --object-name"));
1385
1386 strObjectName = ValueUnion.psz;
1387 if (strObjectName.isEmpty())
1388 return errorArgument(Cloud::tr("Empty parameter: --object-name"));
1389
1390 break;
1391 }
1392
1393 case 'i': /* --id */
1394 {
1395 if (strImageId.isNotEmpty())
1396 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
1397
1398 strImageId = ValueUnion.psz;
1399 if (strImageId.isEmpty())
1400 return errorArgument(Cloud::tr("Empty parameter: --id"));
1401
1402 break;
1403 }
1404
1405 case 'd': /* --display-name */
1406 {
1407 if (strDisplayName.isNotEmpty())
1408 return errorArgument(Cloud::tr("Duplicate parameter: --display-name"));
1409
1410 strDisplayName = ValueUnion.psz;
1411 if (strDisplayName.isEmpty())
1412 return errorArgument(Cloud::tr("Empty parameter: --display-name"));
1413
1414 break;
1415 }
1416
1417 case 'm': /* --launch-mode */
1418 {
1419 if (strLaunchMode.isNotEmpty())
1420 return errorArgument(Cloud::tr("Duplicate parameter: --launch-mode"));
1421
1422 strLaunchMode = ValueUnion.psz;
1423 if (strLaunchMode.isEmpty())
1424 return errorArgument(Cloud::tr("Empty parameter: --launch-mode"));
1425
1426 break;
1427 }
1428
1429 case 'h':
1430 printHelp(g_pStdOut);
1431 return RTEXITCODE_SUCCESS;
1432
1433 case VINF_GETOPT_NOT_OPTION:
1434 return errorUnknownSubcommand(ValueUnion.psz);
1435
1436 default:
1437 return errorGetOpt(c, &ValueUnion);
1438 }
1439 }
1440
1441 /* Delayed check. It allows us to print help information.*/
1442 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1443 if (FAILED(hrc))
1444 return RTEXITCODE_FAILURE;
1445
1446 if (strImageId.isNotEmpty())
1447 BstrFmt("image-id=%s", strImageId.c_str()).detachTo(parameters.appendedRaw());
1448 else
1449 return errorArgument(Cloud::tr("Missing parameter: --id"));
1450
1451 if (strBucketName.isNotEmpty())
1452 BstrFmt("bucket-name=%s", strBucketName.c_str()).detachTo(parameters.appendedRaw());
1453 else
1454 return errorArgument(Cloud::tr("Missing parameter: --bucket-name"));
1455
1456 if (strObjectName.isNotEmpty())
1457 BstrFmt("object-name=%s", strObjectName.c_str()).detachTo(parameters.appendedRaw());
1458
1459 if (strDisplayName.isNotEmpty())
1460 BstrFmt("display-name=%s", strDisplayName.c_str()).detachTo(parameters.appendedRaw());
1461
1462 if (strLaunchMode.isNotEmpty())
1463 BstrFmt("launch-mode=%s", strLaunchMode.c_str()).detachTo(parameters.appendedRaw());
1464
1465
1466 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1467
1468 ComObjPtr<ICloudClient> oCloudClient;
1469 CHECK_ERROR2_RET(hrc, pCloudProfile,
1470 CreateCloudClient(oCloudClient.asOutParam()),
1471 RTEXITCODE_FAILURE);
1472
1473 if (strObjectName.isNotEmpty())
1474 RTPrintf(Cloud::tr("Exporting image \'%s\' to the Cloud with name \'%s\'...\n"),
1475 strImageId.c_str(), strObjectName.c_str());
1476 else
1477 RTPrintf(Cloud::tr("Exporting image \'%s\' to the Cloud with default name\n"),
1478 strImageId.c_str());
1479
1480 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
1481 SafeIfaceArray<IMedium> aImageList;
1482 CHECK_ERROR2_RET(hrc, pVirtualBox,
1483 COMGETTER(HardDisks)(ComSafeArrayAsOutParam(aImageList)),
1484 RTEXITCODE_FAILURE);
1485
1486 ComPtr<IMedium> pImage;
1487 size_t cImages = aImageList.size();
1488 bool fFound = false;
1489 for (size_t i = 0; i < cImages; ++i)
1490 {
1491 pImage = aImageList[i];
1492 Bstr bstrImageId;
1493 hrc = pImage->COMGETTER(Id)(bstrImageId.asOutParam());
1494 if (FAILED(hrc))
1495 continue;
1496
1497 com::Guid imageId(bstrImageId);
1498
1499 if (!imageId.isValid() || imageId.isZero())
1500 continue;
1501
1502 if (!strImageId.compare(imageId.toString()))
1503 {
1504 fFound = true;
1505 RTPrintf(Cloud::tr("Image %s was found\n"), strImageId.c_str());
1506 break;
1507 }
1508 }
1509
1510 if (!fFound)
1511 {
1512 RTPrintf(Cloud::tr("Process of exporting the image to the Cloud was interrupted. The image wasn't found.\n"));
1513 return RTEXITCODE_FAILURE;
1514 }
1515
1516 ComPtr<IProgress> progress;
1517 CHECK_ERROR2_RET(hrc, oCloudClient,
1518 ExportImage(pImage, ComSafeArrayAsInParam(parameters), progress.asOutParam()),
1519 RTEXITCODE_FAILURE);
1520 hrc = showProgress(progress);
1521 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Export the image to the Cloud failed")), RTEXITCODE_FAILURE);
1522
1523 if (SUCCEEDED(hrc))
1524 RTPrintf(Cloud::tr("Export the image to the Cloud was successfull\n"));
1525
1526 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1527}
1528
1529static RTEXITCODE importCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1530{
1531 HRESULT hrc = S_OK;
1532
1533 static const RTGETOPTDEF s_aOptions[] =
1534 {
1535 { "--id", 'i', RTGETOPT_REQ_STRING },
1536 { "--bucket-name", 'b', RTGETOPT_REQ_STRING },
1537 { "--object-name", 'o', RTGETOPT_REQ_STRING },
1538 { "help", 'h', RTGETOPT_REQ_NOTHING },
1539 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1540 };
1541 RTGETOPTSTATE GetState;
1542 RTGETOPTUNION ValueUnion;
1543 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1544 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1545 if (a->argc == iFirst)
1546 {
1547 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1548 printHelp(g_pStdOut);
1549 return RTEXITCODE_SUCCESS;
1550 }
1551
1552 Utf8Str strImageId;
1553 Utf8Str strCompartmentId;
1554 Utf8Str strBucketName;
1555 Utf8Str strObjectName;
1556 Utf8Str strDisplayName;
1557 com::SafeArray<BSTR> parameters;
1558
1559 int c;
1560 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1561 {
1562 switch (c)
1563 {
1564 case 'i':
1565 strImageId=ValueUnion.psz;
1566 break;
1567 case 'b':
1568 strBucketName=ValueUnion.psz;
1569 Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1570 break;
1571 case 'o':
1572 strObjectName=ValueUnion.psz;
1573 Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw());
1574 break;
1575 case 'h':
1576 printHelp(g_pStdOut);
1577 return RTEXITCODE_SUCCESS;
1578 case VINF_GETOPT_NOT_OPTION:
1579 return errorUnknownSubcommand(ValueUnion.psz);
1580 default:
1581 return errorGetOpt(c, &ValueUnion);
1582 }
1583 }
1584
1585 /* Delayed check. It allows us to print help information.*/
1586 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1587 if (FAILED(hrc))
1588 return RTEXITCODE_FAILURE;
1589
1590 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1591
1592 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
1593 ComObjPtr<ICloudClient> oCloudClient;
1594 CHECK_ERROR2_RET(hrc, pCloudProfile,
1595 CreateCloudClient(oCloudClient.asOutParam()),
1596 RTEXITCODE_FAILURE);
1597 RTPrintf(Cloud::tr("Creating an object \'%s\' from the cloud image \'%s\'...\n"), strObjectName.c_str(), strImageId.c_str());
1598
1599 ComPtr<IProgress> progress;
1600 CHECK_ERROR2_RET(hrc, oCloudClient,
1601 ImportImage(Bstr(strImageId).raw(), ComSafeArrayAsInParam(parameters), progress.asOutParam()),
1602 RTEXITCODE_FAILURE);
1603 hrc = showProgress(progress);
1604 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Cloud image import failed")), RTEXITCODE_FAILURE);
1605
1606 if (SUCCEEDED(hrc))
1607 {
1608 RTPrintf(Cloud::tr("Cloud image was imported successfully. Find the downloaded object with the name %s "
1609 "in the system temp folder (find the possible environment variables like TEMP, TMP and etc.)\n"),
1610 strObjectName.c_str());
1611 }
1612
1613 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1614}
1615
1616static RTEXITCODE showCloudImageInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1617{
1618 HRESULT hrc = S_OK;
1619
1620 static const RTGETOPTDEF s_aOptions[] =
1621 {
1622 { "--id", 'i', RTGETOPT_REQ_STRING },
1623 { "help", 'h', RTGETOPT_REQ_NOTHING },
1624 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1625 };
1626 RTGETOPTSTATE GetState;
1627 RTGETOPTUNION ValueUnion;
1628 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1629 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1630 if (a->argc == iFirst)
1631 {
1632 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1633 printHelp(g_pStdOut);
1634 return RTEXITCODE_SUCCESS;
1635 }
1636
1637 Utf8Str strImageId;
1638
1639 int c;
1640 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1641 {
1642 switch (c)
1643 {
1644 case 'i':
1645 strImageId = ValueUnion.psz;
1646 break;
1647 case 'h':
1648 printHelp(g_pStdOut);
1649 return RTEXITCODE_SUCCESS;
1650 case VINF_GETOPT_NOT_OPTION:
1651 return errorUnknownSubcommand(ValueUnion.psz);
1652 default:
1653 return errorGetOpt(c, &ValueUnion);
1654 }
1655 }
1656
1657 /* Delayed check. It allows us to print help information.*/
1658 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1659 if (FAILED(hrc))
1660 return RTEXITCODE_FAILURE;
1661
1662 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1663
1664 ComObjPtr<ICloudClient> oCloudClient;
1665 CHECK_ERROR2_RET(hrc, pCloudProfile,
1666 CreateCloudClient(oCloudClient.asOutParam()),
1667 RTEXITCODE_FAILURE);
1668 RTPrintf(Cloud::tr("Getting information about the cloud image with id \'%s\'...\n"), strImageId.c_str());
1669
1670 ComPtr<IStringArray> infoArray;
1671 com::SafeArray<BSTR> pStrInfoArray;
1672 ComPtr<IProgress> pProgress;
1673
1674 RTPrintf(Cloud::tr("Reply is in the form \'image property\' = \'value\'\n"));
1675 CHECK_ERROR2_RET(hrc, oCloudClient,
1676 GetImageInfo(Bstr(strImageId).raw(),
1677 infoArray.asOutParam(),
1678 pProgress.asOutParam()),
1679 RTEXITCODE_FAILURE);
1680
1681 hrc = showProgress(pProgress);
1682 CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Getting information about the cloud image failed")), RTEXITCODE_FAILURE);
1683
1684 CHECK_ERROR2_RET(hrc,
1685 infoArray, COMGETTER(Values)(ComSafeArrayAsOutParam(pStrInfoArray)),
1686 RTEXITCODE_FAILURE);
1687
1688 RTPrintf(Cloud::tr("General information about the image:\n"));
1689 size_t cParamNames = pStrInfoArray.size();
1690 for (size_t k = 0; k < cParamNames; k++)
1691 {
1692 Utf8Str data(pStrInfoArray[k]);
1693 RTPrintf("\t%s\n", data.c_str());
1694 }
1695
1696 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1697}
1698
1699static RTEXITCODE updateCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1700{
1701 RT_NOREF(a);
1702 RT_NOREF(iFirst);
1703 RT_NOREF(pCommonOpts);
1704 return RTEXITCODE_SUCCESS;
1705}
1706
1707static RTEXITCODE deleteCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1708{
1709 HRESULT hrc = S_OK;
1710
1711 static const RTGETOPTDEF s_aOptions[] =
1712 {
1713 { "--id", 'i', RTGETOPT_REQ_STRING },
1714 { "help", 'h', RTGETOPT_REQ_NOTHING },
1715 { "--help", 'h', RTGETOPT_REQ_NOTHING }
1716 };
1717 RTGETOPTSTATE GetState;
1718 RTGETOPTUNION ValueUnion;
1719 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1720 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1721 if (a->argc == iFirst)
1722 {
1723 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1724 printHelp(g_pStdOut);
1725 return RTEXITCODE_SUCCESS;
1726 }
1727
1728 Utf8Str strImageId;
1729
1730 int c;
1731 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1732 {
1733 switch (c)
1734 {
1735 case 'i':
1736 {
1737 if (strImageId.isNotEmpty())
1738 return errorArgument(Cloud::tr("Duplicate parameter: --id"));
1739
1740 strImageId = ValueUnion.psz;
1741 if (strImageId.isEmpty())
1742 return errorArgument(Cloud::tr("Empty parameter: --id"));
1743
1744 break;
1745 }
1746
1747 case 'h':
1748 printHelp(g_pStdOut);
1749 return RTEXITCODE_SUCCESS;
1750 case VINF_GETOPT_NOT_OPTION:
1751 return errorUnknownSubcommand(ValueUnion.psz);
1752
1753 default:
1754 return errorGetOpt(c, &ValueUnion);
1755 }
1756 }
1757
1758 /* Delayed check. It allows us to print help information.*/
1759 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1760 if (FAILED(hrc))
1761 return RTEXITCODE_FAILURE;
1762
1763 if (strImageId.isEmpty())
1764 return errorArgument(Cloud::tr("Missing parameter: --id"));
1765
1766
1767 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
1768
1769 ComObjPtr<ICloudClient> oCloudClient;
1770 CHECK_ERROR2_RET(hrc, pCloudProfile,
1771 CreateCloudClient(oCloudClient.asOutParam()),
1772 RTEXITCODE_FAILURE);
1773 RTPrintf(Cloud::tr("Deleting cloud image with id %s...\n"), strImageId.c_str());
1774
1775 ComPtr<IProgress> progress;
1776 CHECK_ERROR2_RET(hrc, oCloudClient,
1777 DeleteImage(Bstr(strImageId).raw(), progress.asOutParam()),
1778 RTEXITCODE_FAILURE);
1779 hrc = showProgress(progress);
1780 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Deleting cloud image failed")), RTEXITCODE_FAILURE);
1781
1782 if (SUCCEEDED(hrc))
1783 RTPrintf(Cloud::tr("Cloud image was deleted successfully\n"));
1784
1785 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1786}
1787
1788static RTEXITCODE handleCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1789{
1790 enum
1791 {
1792 kCloudImageIota = 1000,
1793 kCloudImage_Create,
1794 kCloudImage_Delete,
1795 kCloudImage_Export,
1796 kCloudImage_Import,
1797 kCloudImage_Info,
1798 kCloudImage_Update,
1799 };
1800
1801 static const RTGETOPTDEF s_aOptions[] =
1802 {
1803 { "create", kCloudImage_Create, RTGETOPT_REQ_NOTHING },
1804 { "delete", kCloudImage_Delete, RTGETOPT_REQ_NOTHING },
1805 { "export", kCloudImage_Export, RTGETOPT_REQ_NOTHING },
1806 { "import", kCloudImage_Import, RTGETOPT_REQ_NOTHING },
1807 { "info", kCloudImage_Info, RTGETOPT_REQ_NOTHING },
1808 { "update", kCloudImage_Update, RTGETOPT_REQ_NOTHING },
1809
1810 { "help", 'h', RTGETOPT_REQ_NOTHING },
1811 { "-?", 'h', RTGETOPT_REQ_NOTHING },
1812 { "-help", 'h', RTGETOPT_REQ_NOTHING },
1813 { "--help", 'h', RTGETOPT_REQ_NOTHING },
1814 };
1815
1816 if (a->argc == iFirst)
1817 {
1818 RTPrintf(Cloud::tr("Empty command parameter list, show help.\n"));
1819 printHelp(g_pStdOut);
1820 return RTEXITCODE_SUCCESS;
1821 }
1822
1823 RTGETOPTSTATE GetState;
1824 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1825 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1826
1827 int c;
1828 RTGETOPTUNION ValueUnion;
1829 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1830 {
1831 switch (c)
1832 {
1833 /* Sub-commands: */
1834 case kCloudImage_Create:
1835 setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_CREATE);
1836 return createCloudImage(a, GetState.iNext, pCommonOpts);
1837
1838 case kCloudImage_Export:
1839 setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_EXPORT);
1840 return exportCloudImage(a, GetState.iNext, pCommonOpts);
1841
1842 case kCloudImage_Import:
1843 setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_IMPORT);
1844 return importCloudImage(a, GetState.iNext, pCommonOpts);
1845
1846 case kCloudImage_Info:
1847 setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_INFO);
1848 return showCloudImageInfo(a, GetState.iNext, pCommonOpts);
1849
1850 case kCloudImage_Update:
1851// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_UPDATE);
1852 return updateCloudImage(a, GetState.iNext, pCommonOpts);
1853
1854 case kCloudImage_Delete:
1855 setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_DELETE);
1856 return deleteCloudImage(a, GetState.iNext, pCommonOpts);
1857
1858 case 'h':
1859 printHelp(g_pStdOut);
1860 return RTEXITCODE_SUCCESS;
1861
1862 case VINF_GETOPT_NOT_OPTION:
1863 return errorUnknownSubcommand(ValueUnion.psz);
1864
1865 default:
1866 return errorGetOpt(c, &ValueUnion);
1867 }
1868 }
1869
1870 return errorNoSubcommand();
1871}
1872
1873#ifdef VBOX_WITH_CLOUD_NET
1874struct CloudNetworkOptions
1875{
1876 BOOL fEnable;
1877 BOOL fDisable;
1878 Bstr strNetworkId;
1879 Bstr strNetworkName;
1880};
1881typedef struct CloudNetworkOptions CLOUDNETOPT;
1882typedef CLOUDNETOPT *PCLOUDNETOPT;
1883
1884static RTEXITCODE createUpdateCloudNetworkCommon(ComPtr<ICloudNetwork> cloudNetwork, CLOUDNETOPT& options, PCLOUDCOMMONOPT pCommonOpts)
1885{
1886 HRESULT hrc = S_OK;
1887
1888 Bstr strProvider = pCommonOpts->provider.pszProviderName;
1889 Bstr strProfile = pCommonOpts->profile.pszProfileName;
1890
1891 if (options.fEnable)
1892 {
1893 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Enabled)(TRUE), RTEXITCODE_FAILURE);
1894 }
1895 if (options.fDisable)
1896 {
1897 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Enabled)(FALSE), RTEXITCODE_FAILURE);
1898 }
1899 if (options.strNetworkId.isNotEmpty())
1900 {
1901 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(NetworkId)(options.strNetworkId.raw()), RTEXITCODE_FAILURE);
1902 }
1903 if (strProvider.isNotEmpty())
1904 {
1905 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Provider)(strProvider.raw()), RTEXITCODE_FAILURE);
1906 }
1907 if (strProfile.isNotEmpty())
1908 {
1909 CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Profile)(strProfile.raw()), RTEXITCODE_FAILURE);
1910 }
1911
1912 return RTEXITCODE_SUCCESS;
1913}
1914
1915
1916static RTEXITCODE createCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1917{
1918 HRESULT hrc = S_OK;
1919 hrc = checkAndSetCommonOptions(a, pCommonOpts);
1920 if (FAILED(hrc))
1921 return RTEXITCODE_FAILURE;
1922
1923 /* Required parameters, the rest is handled in update */
1924 static const RTGETOPTDEF s_aOptions[] =
1925 {
1926 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
1927 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
1928 { "--network-id", 'i', RTGETOPT_REQ_STRING },
1929 { "--name", 'n', RTGETOPT_REQ_STRING },
1930 };
1931
1932 RTGETOPTSTATE GetState;
1933 RTGETOPTUNION ValueUnion;
1934 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1935 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1936
1937 CLOUDNETOPT options;
1938 options.fEnable = FALSE;
1939 options.fDisable = FALSE;
1940
1941 int c;
1942 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
1943 {
1944 switch (c)
1945 {
1946 case 'd':
1947 options.fDisable = TRUE;
1948 break;
1949 case 'e':
1950 options.fEnable = TRUE;
1951 break;
1952 case 'i':
1953 options.strNetworkId=ValueUnion.psz;
1954 break;
1955 case 'n':
1956 options.strNetworkName=ValueUnion.psz;
1957 break;
1958 case VINF_GETOPT_NOT_OPTION:
1959 return errorUnknownSubcommand(ValueUnion.psz);
1960 default:
1961 return errorGetOpt(c, &ValueUnion);
1962 }
1963 }
1964
1965 if (options.strNetworkName.isEmpty())
1966 return errorArgument(Cloud::tr("Missing --name parameter"));
1967 if (options.strNetworkId.isEmpty())
1968 return errorArgument(Cloud::tr("Missing --network-id parameter"));
1969
1970 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
1971
1972 ComPtr<ICloudNetwork> cloudNetwork;
1973 CHECK_ERROR2_RET(hrc, pVirtualBox,
1974 CreateCloudNetwork(options.strNetworkName.raw(), cloudNetwork.asOutParam()),
1975 RTEXITCODE_FAILURE);
1976
1977 /* Fill out the created network */
1978 RTEXITCODE rc = createUpdateCloudNetworkCommon(cloudNetwork, options, pCommonOpts);
1979 if (RT_SUCCESS(rc))
1980 RTPrintf(Cloud::tr("Cloud network was created successfully\n"));
1981
1982 return rc;
1983}
1984
1985
1986static RTEXITCODE showCloudNetworkInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
1987{
1988 RT_NOREF(pCommonOpts);
1989 HRESULT hrc = S_OK;
1990 static const RTGETOPTDEF s_aOptions[] =
1991 {
1992 { "--name", 'n', RTGETOPT_REQ_STRING },
1993 };
1994 RTGETOPTSTATE GetState;
1995 RTGETOPTUNION ValueUnion;
1996 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
1997 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
1998
1999 Bstr strNetworkName;
2000
2001 int c;
2002 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2003 {
2004 switch (c)
2005 {
2006 case 'n':
2007 strNetworkName=ValueUnion.psz;
2008 break;
2009 case VINF_GETOPT_NOT_OPTION:
2010 return errorUnknownSubcommand(ValueUnion.psz);
2011 default:
2012 return errorGetOpt(c, &ValueUnion);
2013 }
2014 }
2015
2016 if (strNetworkName.isEmpty())
2017 return errorArgument(Cloud::tr("Missing --name parameter"));
2018
2019 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2020 ComPtr<ICloudNetwork> cloudNetwork;
2021 CHECK_ERROR2_RET(hrc, pVirtualBox,
2022 FindCloudNetworkByName(strNetworkName.raw(), cloudNetwork.asOutParam()),
2023 RTEXITCODE_FAILURE);
2024
2025 RTPrintf(Cloud::tr("Name: %ls\n"), strNetworkName.raw());
2026 BOOL fEnabled = FALSE;
2027 cloudNetwork->COMGETTER(Enabled)(&fEnabled);
2028 RTPrintf(Cloud::tr("State: %s\n"), fEnabled ? Cloud::tr("Enabled") : Cloud::tr("Disabled"));
2029 Bstr Provider;
2030 cloudNetwork->COMGETTER(Provider)(Provider.asOutParam());
2031 RTPrintf(Cloud::tr("CloudProvider: %ls\n"), Provider.raw());
2032 Bstr Profile;
2033 cloudNetwork->COMGETTER(Profile)(Profile.asOutParam());
2034 RTPrintf(Cloud::tr("CloudProfile: %ls\n"), Profile.raw());
2035 Bstr NetworkId;
2036 cloudNetwork->COMGETTER(NetworkId)(NetworkId.asOutParam());
2037 RTPrintf(Cloud::tr("CloudNetworkId: %ls\n"), NetworkId.raw());
2038 Bstr netName = BstrFmt("cloud-%ls", strNetworkName.raw());
2039 RTPrintf(Cloud::tr("VBoxNetworkName: %ls\n\n"), netName.raw());
2040
2041 return RTEXITCODE_SUCCESS;
2042}
2043
2044
2045static RTEXITCODE updateCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2046{
2047 HRESULT hrc = S_OK;
2048
2049 static const RTGETOPTDEF s_aOptions[] =
2050 {
2051 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
2052 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
2053 { "--network-id", 'i', RTGETOPT_REQ_STRING },
2054 { "--name", 'n', RTGETOPT_REQ_STRING },
2055 };
2056
2057 RTGETOPTSTATE GetState;
2058 RTGETOPTUNION ValueUnion;
2059 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2060 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2061
2062 CLOUDNETOPT options;
2063 options.fEnable = FALSE;
2064 options.fDisable = FALSE;
2065
2066 int c;
2067 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2068 {
2069 switch (c)
2070 {
2071 case 'd':
2072 options.fDisable = TRUE;
2073 break;
2074 case 'e':
2075 options.fEnable = TRUE;
2076 break;
2077 case 'i':
2078 options.strNetworkId=ValueUnion.psz;
2079 break;
2080 case 'n':
2081 options.strNetworkName=ValueUnion.psz;
2082 break;
2083 case VINF_GETOPT_NOT_OPTION:
2084 return errorUnknownSubcommand(ValueUnion.psz);
2085 default:
2086 return errorGetOpt(c, &ValueUnion);
2087 }
2088 }
2089
2090 if (options.strNetworkName.isEmpty())
2091 return errorArgument(Cloud::tr("Missing --name parameter"));
2092
2093 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2094 ComPtr<ICloudNetwork> cloudNetwork;
2095 CHECK_ERROR2_RET(hrc, pVirtualBox,
2096 FindCloudNetworkByName(options.strNetworkName.raw(), cloudNetwork.asOutParam()),
2097 RTEXITCODE_FAILURE);
2098
2099 RTEXITCODE rc = createUpdateCloudNetworkCommon(cloudNetwork, options, pCommonOpts);
2100 if (RT_SUCCESS(rc))
2101 RTPrintf(Cloud::tr("Cloud network %ls was updated successfully\n"), options.strNetworkName.raw());
2102
2103 return rc;
2104}
2105
2106
2107static RTEXITCODE deleteCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2108{
2109 RT_NOREF(pCommonOpts);
2110 HRESULT hrc = S_OK;
2111 static const RTGETOPTDEF s_aOptions[] =
2112 {
2113 { "--name", 'n', RTGETOPT_REQ_STRING },
2114 };
2115 RTGETOPTSTATE GetState;
2116 RTGETOPTUNION ValueUnion;
2117 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2118 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2119
2120 Bstr strNetworkName;
2121
2122 int c;
2123 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2124 {
2125 switch (c)
2126 {
2127 case 'n':
2128 strNetworkName=ValueUnion.psz;
2129 break;
2130 case VINF_GETOPT_NOT_OPTION:
2131 return errorUnknownSubcommand(ValueUnion.psz);
2132 default:
2133 return errorGetOpt(c, &ValueUnion);
2134 }
2135 }
2136
2137 if (strNetworkName.isEmpty())
2138 return errorArgument(Cloud::tr("Missing --name parameter"));
2139
2140 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2141 ComPtr<ICloudNetwork> cloudNetwork;
2142 CHECK_ERROR2_RET(hrc, pVirtualBox,
2143 FindCloudNetworkByName(strNetworkName.raw(), cloudNetwork.asOutParam()),
2144 RTEXITCODE_FAILURE);
2145
2146 CHECK_ERROR2_RET(hrc, pVirtualBox,
2147 RemoveCloudNetwork(cloudNetwork),
2148 RTEXITCODE_FAILURE);
2149
2150 if (SUCCEEDED(hrc))
2151 RTPrintf(Cloud::tr("Cloud network %ls was deleted successfully\n"), strNetworkName.raw());
2152
2153 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2154}
2155
2156
2157static RTEXITCODE setupCloudNetworkEnv(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2158{
2159 RT_NOREF(pCommonOpts);
2160 HRESULT hrc = S_OK;
2161 static const RTGETOPTDEF s_aOptions[] =
2162 {
2163 { "--gateway-os-name", 'n', RTGETOPT_REQ_STRING },
2164 { "--gateway-os-version", 'v', RTGETOPT_REQ_STRING },
2165 { "--gateway-shape", 's', RTGETOPT_REQ_STRING },
2166 { "--tunnel-network-name", 't', RTGETOPT_REQ_STRING },
2167 { "--tunnel-network-range", 'r', RTGETOPT_REQ_STRING },
2168 { "--compartment-id", 'c', RTGETOPT_REQ_STRING }
2169 };
2170 RTGETOPTSTATE GetState;
2171 RTGETOPTUNION ValueUnion;
2172 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2173 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2174
2175 Bstr strGatewayOsName;
2176 Bstr strGatewayOsVersion;
2177 Bstr strGatewayShape;
2178 Bstr strTunnelNetworkName;
2179 Bstr strTunnelNetworkRange;
2180 Bstr strCompartmentId;
2181
2182 int c;
2183 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2184 {
2185 switch (c)
2186 {
2187 case 'n':
2188 strGatewayOsName=ValueUnion.psz;
2189 break;
2190 case 'v':
2191 strGatewayOsVersion=ValueUnion.psz;
2192 break;
2193 case 's':
2194 strGatewayShape=ValueUnion.psz;
2195 break;
2196 case 't':
2197 strTunnelNetworkName=ValueUnion.psz;
2198 break;
2199 case 'r':
2200 strTunnelNetworkRange=ValueUnion.psz;
2201 break;
2202 case 'c':
2203 strCompartmentId=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 /* Delayed check. It allows us to print help information.*/
2213 hrc = checkAndSetCommonOptions(a, pCommonOpts);
2214 if (FAILED(hrc))
2215 return RTEXITCODE_FAILURE;
2216
2217 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
2218
2219 RTPrintf(Cloud::tr("Setting up tunnel network in the cloud...\n"));
2220
2221 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
2222
2223 /* Use user-specified profile instead of default one. */
2224 if (strCompartmentId.isNotEmpty())
2225 {
2226 CHECK_ERROR2_RET(hrc, pCloudProfile,
2227 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),
2228 RTEXITCODE_FAILURE);
2229 }
2230
2231 ComObjPtr<ICloudClient> oCloudClient;
2232 CHECK_ERROR2_RET(hrc, pCloudProfile,
2233 CreateCloudClient(oCloudClient.asOutParam()),
2234 RTEXITCODE_FAILURE);
2235
2236 ComPtr<ICloudNetworkEnvironmentInfo> cloudNetworkEnv;
2237 ComPtr<IProgress> progress;
2238 CHECK_ERROR2_RET(hrc, oCloudClient,
2239 SetupCloudNetworkEnvironment(strTunnelNetworkName.raw(), strTunnelNetworkRange.raw(),
2240 strGatewayOsName.raw(), strGatewayOsVersion.raw(), strGatewayShape.raw(),
2241 cloudNetworkEnv.asOutParam(), progress.asOutParam()),
2242 RTEXITCODE_FAILURE);
2243
2244 hrc = showProgress(progress);
2245 CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Setting up cloud network environment failed")), RTEXITCODE_FAILURE);
2246
2247 Bstr tunnelNetworkId;
2248 hrc = cloudNetworkEnv->COMGETTER(TunnelNetworkId)(tunnelNetworkId.asOutParam());
2249 RTPrintf(Cloud::tr("Cloud network environment was set up successfully. Tunnel network id is: %ls\n"), tunnelNetworkId.raw());
2250
2251 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2252}
2253
2254
2255static RTEXITCODE handleCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
2256{
2257 enum
2258 {
2259 kCloudNetworkIota = 1000,
2260 kCloudNetwork_Create,
2261 kCloudNetwork_Delete,
2262 kCloudNetwork_Info,
2263 kCloudNetwork_Setup,
2264 kCloudNetwork_Update,
2265 };
2266
2267 static const RTGETOPTDEF s_aOptions[] =
2268 {
2269 { "create", kCloudNetwork_Create, RTGETOPT_REQ_NOTHING },
2270 { "delete", kCloudNetwork_Delete, RTGETOPT_REQ_NOTHING },
2271 { "info", kCloudNetwork_Info, RTGETOPT_REQ_NOTHING },
2272 { "setup", kCloudNetwork_Setup, RTGETOPT_REQ_NOTHING },
2273 { "update", kCloudNetwork_Update, RTGETOPT_REQ_NOTHING },
2274 };
2275
2276 if (a->argc < 1)
2277 return errorNoSubcommand();
2278
2279 RTGETOPTSTATE GetState;
2280 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
2281 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2282
2283 int c;
2284 RTGETOPTUNION ValueUnion;
2285 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2286 {
2287 switch (c)
2288 {
2289 /* Sub-commands: */
2290 case kCloudNetwork_Create:
2291 return createCloudNetwork(a, GetState.iNext, pCommonOpts);
2292
2293 case kCloudNetwork_Info:
2294 return showCloudNetworkInfo(a, GetState.iNext, pCommonOpts);
2295
2296 case kCloudNetwork_Update:
2297 return updateCloudNetwork(a, GetState.iNext, pCommonOpts);
2298
2299 case kCloudNetwork_Delete:
2300 return deleteCloudNetwork(a, GetState.iNext, pCommonOpts);
2301
2302 case kCloudNetwork_Setup:
2303 return setupCloudNetworkEnv(a, GetState.iNext, pCommonOpts);
2304
2305 case VINF_GETOPT_NOT_OPTION:
2306 return errorUnknownSubcommand(ValueUnion.psz);
2307
2308 default:
2309 return errorGetOpt(c, &ValueUnion);
2310 }
2311 }
2312
2313 return errorNoSubcommand();
2314}
2315#endif /* VBOX_WITH_CLOUD_NET */
2316
2317
2318RTEXITCODE handleCloud(HandlerArg *a)
2319{
2320 enum
2321 {
2322 kCloudIota = 1000,
2323 kCloud_Image,
2324 kCloud_Instance,
2325 kCloud_List,
2326 kCloud_Machine,
2327 kCloud_Network,
2328 kCloud_Object,
2329 kCloud_ShowVMInfo,
2330 kCloud_Volume,
2331 };
2332
2333 static const RTGETOPTDEF s_aOptions[] =
2334 {
2335 /* common options */
2336 { "--provider", 'v', RTGETOPT_REQ_STRING },
2337 { "--profile", 'f', RTGETOPT_REQ_STRING },
2338
2339 { "image", kCloud_Image, RTGETOPT_REQ_NOTHING },
2340 { "instance", kCloud_Instance, RTGETOPT_REQ_NOTHING },
2341 { "list", kCloud_List, RTGETOPT_REQ_NOTHING },
2342 { "machine", kCloud_Machine, RTGETOPT_REQ_NOTHING },
2343 { "network", kCloud_Network, RTGETOPT_REQ_NOTHING },
2344 { "object", kCloud_Object, RTGETOPT_REQ_NOTHING },
2345 { "showvminfo", kCloud_ShowVMInfo, RTGETOPT_REQ_NOTHING },
2346 { "volume", kCloud_Volume, RTGETOPT_REQ_NOTHING },
2347 };
2348
2349 if (a->argc < 1)
2350 return errorNoSubcommand();
2351
2352 RTGETOPTSTATE GetState;
2353 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
2354 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
2355
2356 CLOUDCOMMONOPT commonOpts = { {NULL, NULL}, {NULL, NULL} };
2357 int c;
2358 RTGETOPTUNION ValueUnion;
2359 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
2360 {
2361 switch (c)
2362 {
2363 case 'v': // --provider
2364 commonOpts.provider.pszProviderName = ValueUnion.psz;
2365 break;
2366
2367 case 'f': // --profile
2368 commonOpts.profile.pszProfileName = ValueUnion.psz;
2369 break;
2370
2371 /* Sub-commands: */
2372 case kCloud_List:
2373 return handleCloudLists(a, GetState.iNext, &commonOpts);
2374
2375 case kCloud_Image:
2376 return handleCloudImage(a, GetState.iNext, &commonOpts);
2377
2378 case kCloud_Instance:
2379 return handleCloudInstance(a, GetState.iNext, &commonOpts);
2380
2381#ifdef VBOX_WITH_CLOUD_NET
2382 case kCloud_Network:
2383 return handleCloudNetwork(a, GetState.iNext, &commonOpts);
2384#endif /* VBOX_WITH_CLOUD_NET */
2385
2386 /* "cloud machine ..." handling is in VBoxManageCloudMachine.cpp */
2387 case kCloud_Machine:
2388 return handleCloudMachine(a, GetState.iNext,
2389 commonOpts.provider.pszProviderName,
2390 commonOpts.profile.pszProfileName);
2391
2392 /* ... including aliases that mimic the local vm commands */
2393 case kCloud_ShowVMInfo:
2394 return handleCloudShowVMInfo(a, GetState.iNext,
2395 commonOpts.provider.pszProviderName,
2396 commonOpts.profile.pszProfileName);
2397
2398 case VINF_GETOPT_NOT_OPTION:
2399 return errorUnknownSubcommand(ValueUnion.psz);
2400
2401 default:
2402 return errorGetOpt(c, &ValueUnion);
2403 }
2404 }
2405
2406 return errorNoSubcommand();
2407}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use