VirtualBox

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

Last change on this file since 98701 was 98701, checked in by vboxsync, 2 years ago

bugref:10365. OCI stuff. Initial version of the command 'reset' for an instance. The command implements 'hard reset': no gently waiting, just power off, next power on.

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

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