VirtualBox

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

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

bugref:9436. Added 3 commands which start/stop/terminate an instance.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.9 KB
Line 
1/* $Id: VBoxManageCloud.cpp 78734 2019-05-24 19:28:12Z 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 };
113 RTGETOPTSTATE GetState;
114 RTGETOPTUNION ValueUnion;
115 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
116 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
117
118 Utf8Str strCompartmentId;
119 int c;
120 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
121 {
122 switch (c)
123 {
124 case 'c':
125 strCompartmentId = ValueUnion.psz;
126 break;
127 case VINF_GETOPT_NOT_OPTION:
128 return errorUnknownSubcommand(ValueUnion.psz);
129 default:
130 return errorGetOpt(c, &ValueUnion);
131 }
132 }
133
134 HRESULT hrc = S_OK;
135 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
136 ComPtr<ICloudProviderManager> pCloudProviderManager;
137 CHECK_ERROR2_RET(hrc, pVirtualBox,
138 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
139 RTEXITCODE_FAILURE);
140 ComPtr<ICloudProvider> pCloudProvider;
141
142 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
143 GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()),
144 RTEXITCODE_FAILURE);
145 ComPtr<ICloudProfile> pCloudProfile;
146
147 CHECK_ERROR2_RET(hrc, pCloudProvider,
148 GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()),
149 RTEXITCODE_FAILURE);
150
151 if (strCompartmentId.isNotEmpty())
152 {
153 CHECK_ERROR2_RET(hrc, pCloudProfile,
154 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),
155 RTEXITCODE_FAILURE);
156 }
157 else
158 {
159 RTPrintf("Parameter \'compartment\' is empty or absent.\n"
160 "Trying to get the compartment from the passed cloud profile \'%s\'\n", pCommonOpts->profile.pszProfileName);
161 Bstr bStrCompartmentId;
162 CHECK_ERROR2_RET(hrc, pCloudProfile,
163 GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()),
164 RTEXITCODE_FAILURE);
165 strCompartmentId = bStrCompartmentId;
166 if (strCompartmentId.isNotEmpty())
167 RTPrintf("Found the compartment \'%s\':\n", strCompartmentId.c_str());
168 else
169 return errorSyntax(USAGE_S_NEWCMD, "Parameter --compartment-id is required");
170 }
171
172 Bstr bstrProfileName;
173 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
174
175 ComObjPtr<ICloudClient> oCloudClient;
176 CHECK_ERROR2_RET(hrc, pCloudProfile,
177 CreateCloudClient(oCloudClient.asOutParam()),
178 RTEXITCODE_FAILURE);
179
180 ComPtr<IStringArray> pVMNamesHolder;
181 ComPtr<IStringArray> pVMIdsHolder;
182 com::SafeArray<BSTR> arrayVMNames;
183 com::SafeArray<BSTR> arrayVMIds;
184 ComPtr<IProgress> pProgress;
185
186 RTPrintf("Getting a list of available cloud instances...\n");
187 RTPrintf("Reply is in the form \'instance name\' = \'instance id\'\n");
188 CHECK_ERROR2_RET(hrc, oCloudClient,
189 ListInstances(CloudMachineState_Running,
190 pVMNamesHolder.asOutParam(),
191 pVMIdsHolder.asOutParam(),
192 pProgress.asOutParam()),
193 RTEXITCODE_FAILURE);
194 showProgress(pProgress);
195 CHECK_PROGRESS_ERROR_RET(pProgress, ("Failed to list instances"), RTEXITCODE_FAILURE);
196
197 CHECK_ERROR2_RET(hrc,
198 pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)),
199 RTEXITCODE_FAILURE);
200 CHECK_ERROR2_RET(hrc,
201 pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)),
202 RTEXITCODE_FAILURE);
203
204 RTPrintf("List of running instances for the cloud profile \'%ls\' \nand compartment \'%s\':\n",
205 bstrProfileName.raw(), strCompartmentId.c_str());
206 size_t cIds = arrayVMIds.size();
207 size_t cNames = arrayVMNames.size();
208 for (size_t k = 0; k < cNames; k++)
209 {
210 Bstr value;
211 if (k < cIds)
212 value = arrayVMIds[k];
213 RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw());
214 }
215
216 pVMNamesHolder.setNull();
217 pVMIdsHolder.setNull();
218 arrayVMNames.setNull();
219 arrayVMIds.setNull();
220 pProgress.setNull();
221 CHECK_ERROR2_RET(hrc, oCloudClient,
222 ListInstances(CloudMachineState_Stopped,
223 pVMNamesHolder.asOutParam(),
224 pVMIdsHolder.asOutParam(),
225 pProgress.asOutParam()),
226 RTEXITCODE_FAILURE);
227 showProgress(pProgress);
228 CHECK_PROGRESS_ERROR_RET(pProgress, ("Failed to list instances"), RTEXITCODE_FAILURE);
229
230 CHECK_ERROR2_RET(hrc,
231 pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)),
232 RTEXITCODE_FAILURE);
233 CHECK_ERROR2_RET(hrc,
234 pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)),
235 RTEXITCODE_FAILURE);
236
237 RTPrintf("List of paused instances for the cloud profile \'%ls\' \nand compartment \'%s\':\n",
238 bstrProfileName.raw(), strCompartmentId.c_str());
239 cNames = arrayVMNames.size();
240 cIds = arrayVMIds.size();
241 for (size_t k = 0; k < cNames; k++)
242 {
243 Bstr value;
244 if (k < cIds)
245 value = arrayVMIds[k];
246 RTPrintf("\t%ls=%ls\n", arrayVMNames[k], value.raw());
247 }
248
249 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
250}
251
252/**
253 * List all available cloud images for the specified cloud provider.
254 *
255 * @returns RTEXITCODE
256 * @param a is the list of passed arguments
257 * @param iFirst is the position of the first unparsed argument in the arguments list
258 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
259 * arguments which have been already parsed before
260 */
261static RTEXITCODE listCloudImages(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
262{
263 static const RTGETOPTDEF s_aOptions[] =
264 {
265 { "--compartment-id", 'c', RTGETOPT_REQ_STRING }
266 };
267 RTGETOPTSTATE GetState;
268 RTGETOPTUNION ValueUnion;
269 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
270 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
271
272 Utf8Str strCompartmentId;
273 int c;
274 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
275 {
276 switch (c)
277 {
278 case 'c':
279 strCompartmentId = ValueUnion.psz;
280 break;
281 case VINF_GETOPT_NOT_OPTION:
282 return errorUnknownSubcommand(ValueUnion.psz);
283 default:
284 return errorGetOpt(c, &ValueUnion);
285 }
286 }
287
288 HRESULT hrc = S_OK;
289 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
290 ComPtr<ICloudProviderManager> pCloudProviderManager;
291 CHECK_ERROR2_RET(hrc, pVirtualBox,
292 COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()),
293 RTEXITCODE_FAILURE);
294 ComPtr<ICloudProvider> pCloudProvider;
295
296 CHECK_ERROR2_RET(hrc, pCloudProviderManager,
297 GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()),
298 RTEXITCODE_FAILURE);
299 ComPtr<ICloudProfile> pCloudProfile;
300
301 CHECK_ERROR2_RET(hrc, pCloudProvider,
302 GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()),
303 RTEXITCODE_FAILURE);
304 if (strCompartmentId.isNotEmpty())
305 {
306 CHECK_ERROR2_RET(hrc, pCloudProfile,
307 SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),\
308 RTEXITCODE_FAILURE);
309 }
310 else
311 {
312 RTPrintf("Parameter \'compartment\' is empty or absent.\n"
313 "Trying to get the compartment from the passed cloud profile \'%s\'\n", pCommonOpts->profile.pszProfileName);
314 Bstr bStrCompartmentId;
315 CHECK_ERROR2_RET(hrc, pCloudProfile,
316 GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()),
317 RTEXITCODE_FAILURE);
318 strCompartmentId = bStrCompartmentId;
319 if (strCompartmentId.isNotEmpty())
320 RTPrintf("Found the compartment \'%s\':\n", strCompartmentId.c_str());
321 else
322 return errorSyntax(USAGE_S_NEWCMD, "Parameter --compartment-id is required");
323 }
324
325 Bstr bstrProfileName;
326 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
327
328 ComObjPtr<ICloudClient> oCloudClient;
329 CHECK_ERROR2_RET(hrc, pCloudProfile,
330 CreateCloudClient(oCloudClient.asOutParam()),
331 RTEXITCODE_FAILURE);
332
333 ComPtr<IStringArray> pVMNamesHolder;
334 ComPtr<IStringArray> pVMIdsHolder;
335 com::SafeArray<BSTR> arrayVMNames;
336 com::SafeArray<BSTR> arrayVMIds;
337 ComPtr<IProgress> pProgress;
338
339 RTPrintf("Getting a list of available cloud images...\n");
340 RTPrintf("Reply is in the form \'image name\' = \'image id\'\n");
341 CHECK_ERROR2_RET(hrc, oCloudClient,
342 ListImages(CloudImageState_Available,
343 pVMNamesHolder.asOutParam(),
344 pVMIdsHolder.asOutParam(),
345 pProgress.asOutParam()),
346 RTEXITCODE_FAILURE);
347 showProgress(pProgress);
348 CHECK_PROGRESS_ERROR_RET(pProgress, ("Failed to list images"), RTEXITCODE_FAILURE);
349
350 CHECK_ERROR2_RET(hrc,
351 pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)),
352 RTEXITCODE_FAILURE);
353 CHECK_ERROR2_RET(hrc,
354 pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)),
355 RTEXITCODE_FAILURE);
356
357 RTPrintf("List of available images for the cloud profile \'%ls\' \nand compartment \'%s\':\n",
358 bstrProfileName.raw(), strCompartmentId.c_str());
359 size_t cNames = arrayVMNames.size();
360 size_t cIds = arrayVMIds.size();
361 for (size_t k = 0; k < cNames; k++)
362 {
363 Bstr value;
364 if (k < cIds)
365 value = arrayVMIds[k];
366 RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw());
367 }
368
369 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
370}
371
372/**
373 * General function which handles the "list" commands
374 *
375 * @returns RTEXITCODE
376 * @param a is the list of passed arguments
377 * @param iFirst is the position of the first unparsed argument in the arguments list
378 * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common
379 * arguments which have been already parsed before
380 */
381static RTEXITCODE handleCloudLists(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
382{
383 if (a->argc < 1)
384 return errorNoSubcommand();
385
386 static const RTGETOPTDEF s_aOptions[] =
387 {
388 { "images", 1000, RTGETOPT_REQ_NOTHING },
389 { "instances", 1001, RTGETOPT_REQ_NOTHING },
390 { "networks", 1002, RTGETOPT_REQ_NOTHING },
391 { "subnets", 1003, RTGETOPT_REQ_NOTHING },
392 { "vcns", 1004, RTGETOPT_REQ_NOTHING },
393 { "objects", 1005, RTGETOPT_REQ_NOTHING }
394 };
395
396 Bstr bstrProvider(pCommonOpts->provider.pszProviderName);
397 Bstr bstrProfile(pCommonOpts->profile.pszProfileName);
398
399 /* check for required options */
400 if (bstrProvider.isEmpty())
401 return errorSyntax(USAGE_S_NEWCMD, "Parameter --provider is required");
402 if (bstrProfile.isEmpty())
403 return errorSyntax(USAGE_S_NEWCMD, "Parameter --profile is required");
404
405 RTGETOPTSTATE GetState;
406 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
407 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
408
409 int c;
410 RTGETOPTUNION ValueUnion;
411 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
412 {
413 switch (c)
414 {
415 case 1000:
416// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_LIST);
417 return listCloudImages(a, GetState.iNext, pCommonOpts);
418 case 1001:
419// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_LIST);
420 return listCloudInstances(a, GetState.iNext, pCommonOpts);
421 case VINF_GETOPT_NOT_OPTION:
422 return errorUnknownSubcommand(ValueUnion.psz);
423
424 default:
425 return errorGetOpt(c, &ValueUnion);
426 }
427 }
428
429 return errorNoSubcommand();
430}
431
432static RTEXITCODE createCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
433{
434 RT_NOREF(iFirst);
435 RT_NOREF(pCommonOpts);
436 return RTEXITCODE_SUCCESS;
437}
438
439static RTEXITCODE updateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
440{
441 RT_NOREF(iFirst);
442 RT_NOREF(pCommonOpts);
443 return RTEXITCODE_SUCCESS;
444}
445
446static RTEXITCODE showCloudInstanceInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
447{
448 HRESULT hrc = S_OK;
449
450 hrc = checkAndSetCommonOptions(a, pCommonOpts);
451 if (FAILED(hrc))
452 return RTEXITCODE_FAILURE;
453
454 static const RTGETOPTDEF s_aOptions[] =
455 {
456 { "--id", 'i', RTGETOPT_REQ_STRING }
457 };
458 RTGETOPTSTATE GetState;
459 RTGETOPTUNION ValueUnion;
460 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
461 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
462
463 Utf8Str strInstanceId;
464 int c;
465 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
466 {
467 switch (c)
468 {
469 case 'i':
470 strInstanceId = ValueUnion.psz;
471 break;
472 case VINF_GETOPT_NOT_OPTION:
473 return errorUnknownSubcommand(ValueUnion.psz);
474 default:
475 return errorGetOpt(c, &ValueUnion);
476 }
477 }
478
479 Bstr bstrProfileName;
480 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
481 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
482
483 ComObjPtr<ICloudClient> oCloudClient;
484 CHECK_ERROR2_RET(hrc, pCloudProfile,
485 CreateCloudClient(oCloudClient.asOutParam()),
486 RTEXITCODE_FAILURE);
487 RTPrintf("Getting information about cloud instance with id %s...\n", strInstanceId.c_str());
488 RTPrintf("Reply is in the form \'setting name\' = \'value\'\n");
489
490 ComPtr<IAppliance> pAppliance;
491 CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE);
492
493 com::SafeIfaceArray<IVirtualSystemDescription> vsdArray;
494 uint32_t requestedVSDnums = 1;
495 uint32_t newVSDnums = 0;
496 CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(requestedVSDnums, &newVSDnums), RTEXITCODE_FAILURE);
497 if (requestedVSDnums != newVSDnums)
498 return RTEXITCODE_FAILURE;
499
500 CHECK_ERROR2_RET(hrc, pAppliance, COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(vsdArray)), RTEXITCODE_FAILURE);
501 ComPtr<IVirtualSystemDescription> instanceDescription = vsdArray[0];
502 CHECK_ERROR2_RET(hrc, oCloudClient,
503 GetInstanceInfo(Bstr(strInstanceId.c_str()).raw(), instanceDescription),
504 RTEXITCODE_FAILURE);
505 RTPrintf("Cloud instance info (provider '%s'):\n",
506 pCommonOpts->provider.pszProviderName);
507
508 struct vsdHReadable {
509 VirtualSystemDescriptionType_T vsdType;
510 Utf8Str strFound;
511 Utf8Str strNotFound;
512 };
513
514 size_t vsdHReadableArraySize = 9;//the number of items in the vsdHReadableArray
515 vsdHReadable vsdHReadableArray[vsdHReadableArraySize] = {
516 {VirtualSystemDescriptionType_CloudDomain, "Availability domain = '%ls'\n", "Availability domain wasn't found\n"},
517 {VirtualSystemDescriptionType_Name, "Instance displayed name = '%ls'\n", "Instance displayed name wasn't found\n"},
518 {VirtualSystemDescriptionType_CloudInstanceState, "Instance state = '%ls'\n", "Instance state wasn't found\n"},
519 {VirtualSystemDescriptionType_CloudInstanceId, "Instance Id = '%ls'\n", "Instance Id wasn't found\n"},
520 {VirtualSystemDescriptionType_CloudImageId, "Bootable image Id = '%ls'\n",
521 "Image Id whom the instance is booted up wasn't found\n"},
522 {VirtualSystemDescriptionType_CloudInstanceShape, "Shape of the instance = '%ls'\n",
523 "The shape of the instance wasn't found\n"},
524 {VirtualSystemDescriptionType_OS, "Type of guest OS = '%ls'\n", "Type of guest OS wasn't found.\n"},
525 {VirtualSystemDescriptionType_Memory, "RAM = '%ls MB'\n", "Value for RAM wasn't found\n"},
526 {VirtualSystemDescriptionType_CPU, "CPUs = '%ls'\n", "Numbers of CPUs weren't found\n"}
527 };
528
529 com::SafeArray<VirtualSystemDescriptionType_T> retTypes;
530 com::SafeArray<BSTR> aRefs;
531 com::SafeArray<BSTR> aOvfValues;
532 com::SafeArray<BSTR> aVBoxValues;
533 com::SafeArray<BSTR> aExtraConfigValues;
534
535 for (size_t i=0; i<vsdHReadableArraySize ; ++i)
536 {
537 hrc = instanceDescription->GetDescriptionByType(vsdHReadableArray[i].vsdType,
538 ComSafeArrayAsOutParam(retTypes),
539 ComSafeArrayAsOutParam(aRefs),
540 ComSafeArrayAsOutParam(aOvfValues),
541 ComSafeArrayAsOutParam(aVBoxValues),
542 ComSafeArrayAsOutParam(aExtraConfigValues));
543 if (FAILED(hrc) || aVBoxValues.size() == 0)
544 LogRel((vsdHReadableArray[i].strNotFound.c_str()));
545 else
546 RTPrintf(vsdHReadableArray[i].strFound.c_str(), aVBoxValues[0]);
547
548 retTypes.setNull();
549 aRefs.setNull();
550 aOvfValues.setNull();
551 aVBoxValues.setNull();
552 aExtraConfigValues.setNull();
553 }
554
555 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
556}
557
558static RTEXITCODE startCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
559{
560 HRESULT hrc = S_OK;
561 hrc = checkAndSetCommonOptions(a, pCommonOpts);
562 if (FAILED(hrc))
563 return RTEXITCODE_FAILURE;
564
565 static const RTGETOPTDEF s_aOptions[] =
566 {
567 { "--id", 'i', RTGETOPT_REQ_STRING }
568 };
569 RTGETOPTSTATE GetState;
570 RTGETOPTUNION ValueUnion;
571 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
572 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
573
574 Utf8Str strInstanceId;
575 int c;
576 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
577 {
578 switch (c)
579 {
580 case 'i':
581 strInstanceId = ValueUnion.psz;
582 break;
583 case VINF_GETOPT_NOT_OPTION:
584 return errorUnknownSubcommand(ValueUnion.psz);
585 default:
586 return errorGetOpt(c, &ValueUnion);
587 }
588 }
589
590 Bstr bstrProfileName;
591 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
592 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
593
594 ComObjPtr<ICloudClient> oCloudClient;
595 CHECK_ERROR2_RET(hrc, pCloudProfile,
596 CreateCloudClient(oCloudClient.asOutParam()),
597 RTEXITCODE_FAILURE);
598 RTPrintf("Starting cloud instance with id %s...\n", strInstanceId.c_str());
599
600 ComPtr<IProgress> progress;
601 CHECK_ERROR2_RET(hrc, oCloudClient,
602 StartInstance(Bstr(strInstanceId.c_str()).raw(), progress.asOutParam()),
603 RTEXITCODE_FAILURE);
604 hrc = showProgress(progress);
605 CHECK_PROGRESS_ERROR_RET(progress, ("Starting the cloud instance failed"), RTEXITCODE_FAILURE);
606
607 if (SUCCEEDED(hrc))
608 RTPrintf("Cloud instance with id %s (provider = '%s', profile = '%s') was started\n",
609 strInstanceId.c_str(),
610 pCommonOpts->provider.pszProviderName,
611 pCommonOpts->profile.pszProfileName);
612
613 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
614}
615
616static RTEXITCODE pauseCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
617{
618 HRESULT hrc = S_OK;
619 hrc = checkAndSetCommonOptions(a, pCommonOpts);
620
621 if (FAILED(hrc))
622 return RTEXITCODE_FAILURE;
623
624 static const RTGETOPTDEF s_aOptions[] =
625 {
626 { "--id", 'i', RTGETOPT_REQ_STRING }
627 };
628 RTGETOPTSTATE GetState;
629 RTGETOPTUNION ValueUnion;
630 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
631 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
632
633 Utf8Str strInstanceId;
634 int c;
635 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
636 {
637 switch (c)
638 {
639 case 'i':
640 strInstanceId = ValueUnion.psz;
641 break;
642 case VINF_GETOPT_NOT_OPTION:
643 return errorUnknownSubcommand(ValueUnion.psz);
644 default:
645 return errorGetOpt(c, &ValueUnion);
646 }
647 }
648
649 Bstr bstrProfileName;
650 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
651 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
652
653 ComObjPtr<ICloudClient> oCloudClient;
654 CHECK_ERROR2_RET(hrc, pCloudProfile,
655 CreateCloudClient(oCloudClient.asOutParam()),
656 RTEXITCODE_FAILURE);
657 RTPrintf("Pausing cloud instance with id %s...\n", strInstanceId.c_str());
658
659 ComPtr<IProgress> progress;
660 CHECK_ERROR2_RET(hrc, oCloudClient,
661 PauseInstance(Bstr(strInstanceId.c_str()).raw(), progress.asOutParam()),
662 RTEXITCODE_FAILURE);
663 hrc = showProgress(progress);
664 CHECK_PROGRESS_ERROR_RET(progress, ("Pause the cloud instance failed"), RTEXITCODE_FAILURE);
665
666 if (SUCCEEDED(hrc))
667 RTPrintf("Cloud instance with id %s (provider = '%s', profile = '%s') was paused\n",
668 strInstanceId.c_str(),
669 pCommonOpts->provider.pszProviderName,
670 pCommonOpts->profile.pszProfileName);
671
672 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
673}
674
675static RTEXITCODE terminateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
676{
677 HRESULT hrc = S_OK;
678
679 hrc = checkAndSetCommonOptions(a, pCommonOpts);
680 if (FAILED(hrc))
681 return RTEXITCODE_FAILURE;
682
683 static const RTGETOPTDEF s_aOptions[] =
684 {
685 { "--id", 'i', RTGETOPT_REQ_STRING }
686 };
687 RTGETOPTSTATE GetState;
688 RTGETOPTUNION ValueUnion;
689 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
690 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
691
692 Utf8Str strInstanceId;
693 int c;
694 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
695 {
696 switch (c)
697 {
698 case 'i':
699 strInstanceId = ValueUnion.psz;
700 break;
701 case VINF_GETOPT_NOT_OPTION:
702 return errorUnknownSubcommand(ValueUnion.psz);
703 default:
704 return errorGetOpt(c, &ValueUnion);
705 }
706 }
707
708 Bstr bstrProfileName;
709 ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile;
710 pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam());
711
712 ComObjPtr<ICloudClient> oCloudClient;
713 CHECK_ERROR2_RET(hrc, pCloudProfile,
714 CreateCloudClient(oCloudClient.asOutParam()),
715 RTEXITCODE_FAILURE);
716 RTPrintf("Terminating cloud instance with id %s...\n", strInstanceId.c_str());
717
718 ComPtr<IProgress> progress;
719 CHECK_ERROR2_RET(hrc, oCloudClient,
720 TerminateInstance(Bstr(strInstanceId.c_str()).raw(), progress.asOutParam()),
721 RTEXITCODE_FAILURE);
722 hrc = showProgress(progress);
723 CHECK_PROGRESS_ERROR_RET(progress, ("Termination the cloud instance failed"), RTEXITCODE_FAILURE);
724
725 if (SUCCEEDED(hrc))
726 RTPrintf("Cloud instance with id %s (provider = '%s', profile = '%s') was terminated\n",
727 strInstanceId.c_str(),
728 pCommonOpts->provider.pszProviderName,
729 pCommonOpts->profile.pszProfileName);
730
731 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
732}
733
734static RTEXITCODE handleCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts)
735{
736 if (a->argc < 1)
737 return errorNoSubcommand();
738
739 static const RTGETOPTDEF s_aOptions[] =
740 {
741 { "create", 1000, RTGETOPT_REQ_NOTHING },
742 { "start", 1001, RTGETOPT_REQ_NOTHING },
743 { "pause", 1002, RTGETOPT_REQ_NOTHING },
744 { "info", 1003, RTGETOPT_REQ_NOTHING },
745 { "update", 1004, RTGETOPT_REQ_NOTHING },
746 { "terminate", 1005, RTGETOPT_REQ_NOTHING }
747 };
748
749 RTGETOPTSTATE GetState;
750 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
751 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
752
753 int c;
754 RTGETOPTUNION ValueUnion;
755 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
756 {
757 switch (c)
758 {
759 /* Sub-commands: */
760 case 1000:
761// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_CREATE);
762 return createCloudInstance(a, GetState.iNext, pCommonOpts);
763 case 1001:
764 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_START);
765 return startCloudInstance(a, GetState.iNext, pCommonOpts);
766 case 1002:
767 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_PAUSE);
768 return pauseCloudInstance(a, GetState.iNext, pCommonOpts);
769 case 1003:
770 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_INFO);
771 return showCloudInstanceInfo(a, GetState.iNext, pCommonOpts);
772 case 1004:
773// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_UPDATE);
774 return updateCloudInstance(a, GetState.iNext, pCommonOpts);
775 case 1005:
776 setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_TERMINATE);
777 return terminateCloudInstance(a, GetState.iNext, pCommonOpts);
778 case VINF_GETOPT_NOT_OPTION:
779 return errorUnknownSubcommand(ValueUnion.psz);
780
781 default:
782 return errorGetOpt(c, &ValueUnion);
783 }
784 }
785
786 return errorNoSubcommand();
787}
788
789RTEXITCODE handleCloud(HandlerArg *a)
790{
791 if (a->argc < 1)
792 return errorNoSubcommand();
793
794 static const RTGETOPTDEF s_aOptions[] =
795 {
796 /* common options */
797 { "--provider", 'v', RTGETOPT_REQ_STRING },
798 { "--profile", 'f', RTGETOPT_REQ_STRING },
799 { "list", 1000, RTGETOPT_REQ_NOTHING },
800 { "image", 1001, RTGETOPT_REQ_NOTHING },
801 { "instance", 1002, RTGETOPT_REQ_NOTHING },
802 { "network", 1003, RTGETOPT_REQ_NOTHING },
803 { "volume", 1004, RTGETOPT_REQ_NOTHING },
804 { "object", 1005, RTGETOPT_REQ_NOTHING }
805 };
806
807 RTGETOPTSTATE GetState;
808 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
809 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
810
811 CLOUDCOMMONOPT commonOpts = { {NULL, NULL}, {NULL, NULL} };
812 int c;
813 RTGETOPTUNION ValueUnion;
814 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
815 {
816 switch (c)
817 {
818 case 'v': // --provider
819 commonOpts.provider.pszProviderName = ValueUnion.psz;
820 break;
821 case 'f': // --profile
822 commonOpts.profile.pszProfileName = ValueUnion.psz;
823 break;
824 /* Sub-commands: */
825 case 1000:
826 return handleCloudLists(a, GetState.iNext, &commonOpts);
827 case 1002:
828 return handleCloudInstance(a, GetState.iNext, &commonOpts);
829 case VINF_GETOPT_NOT_OPTION:
830 return errorUnknownSubcommand(ValueUnion.psz);
831
832 default:
833 return errorGetOpt(c, &ValueUnion);
834 }
835 }
836
837 return errorNoSubcommand();
838}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use