VirtualBox

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

Last change on this file since 79806 was 79797, checked in by vboxsync, 6 years ago

bugref:9481 - listCloudImages: handle all known values for --state;
report an error if an unknown one is specified; allow multiple --state
options (API call takes an array of states).

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

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