VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageObjectTracker.cpp@ 107155

Last change on this file since 107155 was 107155, checked in by vboxsync, 8 weeks ago

jiraref:VBP-1459. Added new file VBoxManageObjectTracker.cpp

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.1 KB
Line 
1/* $Id: VBoxManageObjectTracker.cpp 107155 2024-11-27 10:27:22Z vboxsync $ */
2/** @file
3 * VBoxManageObjectTracker - The object tracker related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include "VBoxManage.h"
29
30#include <map>
31#include <vector>
32
33using namespace com;
34using namespace std;
35
36//std::vector <com::Utf8Str> supportedIfaceList= {"IProgress", "ISession", "IMedium", "IMachine"};
37
38enum supIfaces_T
39{
40 None = 0,
41 kProgress = 1,
42 kSession,
43 kMedium,
44 kMachine,
45};
46
47std::map <com::Utf8Str, supIfaces_T> mapInterfaceNameToEnum = {
48 {"IProgress", kProgress},
49 {"ISession", kSession},
50 {"IMedium", kMedium},
51 {"IMachine", kMachine}
52};
53
54
55void printProgressObjectInfo(const ComPtr<IProgress>& pObj)
56{
57 if (pObj.isNotNull())
58 {
59 RTPrintf(("Progress:\n"));
60 Bstr bStrAttr;
61 pObj->COMGETTER(Id)(bStrAttr.asOutParam());
62 RTPrintf((" Id %s\n"), Utf8Str(bStrAttr).c_str());
63
64 pObj->COMGETTER(Description)(bStrAttr.asOutParam());
65 RTPrintf((" Description %s\n"), Utf8Str(bStrAttr).c_str());
66
67 BOOL fBoolAttr;
68 pObj->COMGETTER(Completed)(&fBoolAttr);
69 RTPrintf((" Completed %s\n"), fBoolAttr ? "True" : "False");
70
71 pObj->COMGETTER(Canceled)(&fBoolAttr);
72 RTPrintf((" Canceled %s\n"), fBoolAttr ? "True" : "False");
73 }
74}
75
76void printSessionObjectInfo(const ComPtr<ISession>& pObj)
77{
78 if (pObj.isNotNull())
79 {
80 RTPrintf(("Session:\n"));
81 Bstr bStrAttr;
82 pObj->COMGETTER(Name)(bStrAttr.asOutParam());
83 RTPrintf((" Name %s\n"), Utf8Str(bStrAttr).c_str());
84
85 SessionState_T enmState;
86 pObj->COMGETTER(State)(&enmState);
87 RTPrintf((" State %u\n"), enmState);
88
89 SessionType_T enmType;
90 pObj->COMGETTER(Type)(&enmType);
91 RTPrintf((" Type %u\n"), enmType);
92 }
93}
94
95void printMediumObjectInfo(const ComPtr<IMedium>& pObj)
96{
97 if (pObj.isNotNull())
98 {
99 RTPrintf(("Medium:\n"));
100 Bstr bStrAttr;
101 pObj->COMGETTER(Id)(bStrAttr.asOutParam());
102 RTPrintf((" Medium Id %s\n"), Utf8Str(bStrAttr).c_str());
103
104 pObj->COMGETTER(Name)(bStrAttr.asOutParam());
105 RTPrintf((" Name %s\n"), Utf8Str(bStrAttr).c_str());
106
107 pObj->COMGETTER(Description)(bStrAttr.asOutParam());
108 RTPrintf((" Description %s\n"), Utf8Str(bStrAttr).c_str());
109
110 pObj->COMGETTER(Location)(bStrAttr.asOutParam());
111 RTPrintf((" Location %s\n"), Utf8Str(bStrAttr).c_str());
112
113 pObj->COMGETTER(Format)(bStrAttr.asOutParam());
114 RTPrintf((" Format %s\n"), Utf8Str(bStrAttr).c_str());
115
116 pObj->COMGETTER(LastAccessError)(bStrAttr.asOutParam());
117 RTPrintf((" LastAccessError %s\n"), Utf8Str(bStrAttr).c_str());
118
119 MediumState_T enmState;
120 pObj->RefreshState(&enmState);
121 /* check for accessibility */
122 const char *pszState = "unknown";
123 switch (enmState)
124 {
125 case MediumState_NotCreated:
126 pszState = "not created";
127 break;
128 case MediumState_Created:
129 pszState = "created";
130 break;
131 case MediumState_LockedRead:
132 pszState = "locked read";
133 break;
134 case MediumState_LockedWrite:
135 pszState = "locked write";
136 break;
137 case MediumState_Inaccessible:
138 pszState = "inaccessible";
139 break;
140 case MediumState_Creating:
141 pszState = "creating";
142 break;
143 case MediumState_Deleting:
144 pszState = "deleting";
145 break;
146#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
147 case MediumState_32BitHack: break; /* Shut up compiler warnings. */
148#endif
149 }
150 RTPrintf((" State %s\n"), pszState);
151
152 BOOL fBoolAttr;
153 pObj->COMGETTER(HostDrive)(&fBoolAttr);
154 RTPrintf((" HostDrive %s\n"), fBoolAttr ? "True" : "False");
155
156 LONG64 nLongIntAttr;
157 pObj->COMGETTER(LogicalSize)(&nLongIntAttr);
158 RTPrintf((" Logical Size (MB) %ld\n"), nLongIntAttr / _1M);
159
160 pObj->COMGETTER(Size)(&nLongIntAttr);
161 RTPrintf((" Real Size (MB) %ld\n"), nLongIntAttr / _1M);
162 }
163}
164
165void printMachineObjectInfo(const ComPtr<IMachine>& pObj)
166{
167 if (pObj.isNotNull())
168 {
169 RTPrintf(("Machine:\n"));
170
171 Bstr bStrAttr;
172 pObj->COMGETTER(Name)(bStrAttr.asOutParam());
173 RTPrintf((" Name %s\n"), Utf8Str(bStrAttr).c_str());
174
175 BOOL fBoolAttr;
176 pObj->COMGETTER(Accessible)(&fBoolAttr);
177 RTPrintf((" Accessible %s\n"), fBoolAttr ? "True" : "False");
178
179 pObj->COMGETTER(Id)(bStrAttr.asOutParam());
180 RTPrintf((" Machine Id %s\n"), Utf8Str(bStrAttr).c_str());
181
182 pObj->COMGETTER(Description)(bStrAttr.asOutParam());
183 RTPrintf((" Description %s\n"), Utf8Str(bStrAttr).c_str());
184
185 pObj->COMGETTER(OSTypeId)(bStrAttr.asOutParam());
186 RTPrintf((" OSTypeId %s\n"), Utf8Str(bStrAttr).c_str());
187
188 pObj->COMGETTER(HardwareVersion)(bStrAttr.asOutParam());
189 RTPrintf((" HardwareVersion %s\n"), Utf8Str(bStrAttr).c_str());
190
191 pObj->COMGETTER(HardwareUUID)(bStrAttr.asOutParam());
192 RTPrintf((" HardwareUUID %s\n"), Utf8Str(bStrAttr).c_str());
193
194 pObj->COMGETTER(SnapshotFolder)(bStrAttr.asOutParam());
195 RTPrintf((" SnapshotFolder %s\n"), Utf8Str(bStrAttr).c_str());
196
197 pObj->COMGETTER(SettingsFilePath)(bStrAttr.asOutParam());
198 RTPrintf((" SettingsFilePath %s\n"), Utf8Str(bStrAttr).c_str());
199
200 pObj->COMGETTER(SettingsAuxFilePath)(bStrAttr.asOutParam());
201 RTPrintf((" SettingsAuxFilePath %s\n"), Utf8Str(bStrAttr).c_str());
202
203 pObj->COMGETTER(StateFilePath)(bStrAttr.asOutParam());
204 RTPrintf((" StateFilePath %s\n"), Utf8Str(bStrAttr).c_str());
205
206 pObj->COMGETTER(LogFolder)(bStrAttr.asOutParam());
207 RTPrintf((" LogFolder %s\n"), Utf8Str(bStrAttr).c_str());
208
209 ULONG nIntAttr;
210 pObj->COMGETTER(CPUCount)(&nIntAttr);
211 RTPrintf((" CPUCount %ld\n"), nIntAttr);
212
213 pObj->COMGETTER(MemorySize)(&nIntAttr);
214 RTPrintf((" Memory Size (MB) %ld\n"), nIntAttr);
215
216 MachineState_T enmState;
217 pObj->COMGETTER(State)(&enmState);
218 const char *pszState = machineStateToName(enmState, true);
219 RTPrintf((" State %s\n"), pszState);
220 }
221}
222
223void printTrackedObjectInfo(supIfaces_T aIface, const map < Bstr, ComPtr<IUnknown> >& aObjMap)
224{
225 switch (aIface)
226 {
227 case kProgress:
228 for (const pair< const Bstr, ComPtr<IUnknown> >& item : aObjMap)
229 {
230 ComPtr<IProgress> pObj;
231 item.second->QueryInterface(IID_IProgress, (void **)pObj.asOutParam());
232
233 if (pObj.isNotNull())
234 {
235 RTPrintf(("\nTracked object id: %s\n"), Utf8Str(item.first).c_str());
236 printProgressObjectInfo(pObj);
237 }
238 }
239
240 break;
241
242 case kSession:
243 for (const pair< const Bstr, ComPtr<IUnknown> >& item : aObjMap)
244 {
245 ComPtr<ISession> pObj;
246 item.second->QueryInterface(IID_ISession, (void **)pObj.asOutParam());
247
248 if (pObj.isNotNull())
249 {
250 RTPrintf(("\nTracked object id: %s\n"), Utf8Str(item.first).c_str());
251 printSessionObjectInfo(pObj);
252 }
253 }
254
255 break;
256
257 case kMedium:
258 for (const pair< const Bstr, ComPtr<IUnknown> >& item : aObjMap)
259 {
260 ComPtr<IMedium> pObj;
261 item.second->QueryInterface(IID_IMedium, (void **)pObj.asOutParam());
262
263 if (pObj.isNotNull())
264 {
265 RTPrintf(("\nTracked object id: %s\n"), Utf8Str(item.first).c_str());
266 printMediumObjectInfo(pObj);
267 }
268 }
269
270 break;
271
272 case kMachine:
273 for (const pair< const Bstr, ComPtr<IUnknown> >& item : aObjMap)
274 {
275 ComPtr<IMachine> pObj;
276 item.second->QueryInterface(IID_IMachine, (void **)pObj.asOutParam());
277
278 if (pObj.isNotNull())
279 {
280 RTPrintf(("\nTracked object id: %s\n"), Utf8Str(item.first).c_str());
281 printMachineObjectInfo(pObj);
282 }
283 }
284
285 break;
286
287 default:
288 RTPrintf("Interface isn't supported by object tracker at moment");
289 break;
290 }
291}
292
293static RTEXITCODE handleObjInfo(HandlerArg *a, int iFirst)
294{
295 HRESULT hrc = S_OK;
296
297 static const RTGETOPTDEF s_aOptions[] =
298 {
299 { "--id", 'i', RTGETOPT_REQ_STRING },
300 { "--ifacename", 'f', RTGETOPT_REQ_STRING },
301 { "help", 'h', RTGETOPT_REQ_NOTHING },
302 { "--help", 'h', RTGETOPT_REQ_NOTHING }
303 };
304 RTGETOPTSTATE GetState;
305 RTGETOPTUNION ValueUnion;
306 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
307 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
308 if (a->argc == iFirst)
309 {
310 RTPrintf(("Empty command parameter list, show help.\n"));
311 printHelp(g_pStdOut);
312 return RTEXITCODE_SUCCESS;
313 }
314
315 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
316
317 Utf8Str strObjUuid;
318 Utf8Str strIfaceName;
319
320 int c;
321 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
322 {
323 switch (c)
324 {
325 case 'i':
326 {
327 if (strObjUuid.isNotEmpty())
328 return errorArgument("Duplicate parameter: --id");
329
330 strObjUuid = ValueUnion.psz;
331 if (strObjUuid.isEmpty())
332 return errorArgument("Empty parameter: --id");
333
334 break;
335 }
336 case 'f':
337 {
338 if (strIfaceName.isNotEmpty())
339 return errorArgument("Duplicate parameter: --ifacename");
340
341 strIfaceName = ValueUnion.psz;
342 if (strIfaceName.isEmpty())
343 return errorArgument("Empty parameter: --ifacename");
344
345 break;
346 }
347 case 'h':
348 printHelp(g_pStdOut);
349 return RTEXITCODE_SUCCESS;
350 case VINF_GETOPT_NOT_OPTION:
351 return errorUnknownSubcommand(ValueUnion.psz);
352
353 default:
354 return errorGetOpt(c, &ValueUnion);
355 }
356 }
357
358 map <com::Utf8Str, supIfaces_T>::const_iterator cIt = mapInterfaceNameToEnum.find(strIfaceName);
359 if (cIt != mapInterfaceNameToEnum.end())
360 {
361 supIfaces_T foundIface = cIt->second;
362 com::SafeArray<BSTR> ObjIDsList;
363 hrc = pVirtualBox->GetTrackedObjectIds(Bstr(cIt->first).raw(), ComSafeArrayAsOutParam(ObjIDsList));
364 if (SUCCEEDED(hrc))
365 {
366 map < Bstr, ComPtr<IUnknown> > lObjMap;
367 if (strObjUuid.isNotEmpty())
368 {
369 for (size_t i = 0; i < ObjIDsList.size(); ++i)
370 {
371 Bstr bstrObjId = ObjIDsList[i];
372 if (bstrObjId.equals(strObjUuid.c_str()))
373 {
374 ComPtr<IUnknown> pIUnknown;
375 hrc = pVirtualBox->GetTrackedObject(bstrObjId.raw(), pIUnknown.asOutParam());
376 lObjMap[bstrObjId] = pIUnknown;
377 break;
378 }
379 }
380 }
381 else
382 {
383 for (size_t i = 0; i < ObjIDsList.size(); ++i)
384 {
385 Bstr bstrObjId = ObjIDsList[i];
386 ComPtr<IUnknown> pIUnknown;
387 hrc = pVirtualBox->GetTrackedObject(bstrObjId.raw(), pIUnknown.asOutParam());
388 lObjMap[bstrObjId] = pIUnknown;
389 }
390 }
391
392 if (!lObjMap.empty())
393 printTrackedObjectInfo(foundIface, lObjMap);
394 else
395 RTPrintf(("Object with Id %s wasn't found or has \"invalid\" state\n"), strObjUuid.c_str());
396 }
397 }
398 else
399 RTPrintf(("Interface %s isn't supported at present\n"), strIfaceName.c_str());
400
401 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
402}
403
404
405static RTEXITCODE handleSupIfaceList(HandlerArg *a, int iFirst)
406{
407 HRESULT hrc = S_OK;
408
409 static const RTGETOPTDEF s_aOptions[] =
410 {
411 { "help", 'h', RTGETOPT_REQ_NOTHING },
412 { "--help", 'h', RTGETOPT_REQ_NOTHING }
413 };
414 RTGETOPTSTATE GetState;
415 RTGETOPTUNION ValueUnion;
416 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
417 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
418
419 int c;
420 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
421 {
422 switch (c)
423 {
424 case 'h':
425 printHelp(g_pStdOut);
426 return RTEXITCODE_SUCCESS;
427 case VINF_GETOPT_NOT_OPTION:
428 return errorUnknownSubcommand(ValueUnion.psz);
429
430 default:
431 return errorGetOpt(c, &ValueUnion);
432 }
433 }
434
435 RTPrintf(("Supported interfaces:\n"));
436 for (pair<const com::Utf8Str, supIfaces_T>& item : mapInterfaceNameToEnum)
437 RTPrintf((" %s\n"), item.first.c_str());
438
439 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
440}
441
442static RTEXITCODE handleObjectList(HandlerArg *a, int iFirst)
443{
444 HRESULT hrc = S_OK;
445
446 static const RTGETOPTDEF s_aOptions[] =
447 {
448 { "--ifacename", 'f', RTGETOPT_REQ_STRING },
449 { "help", 'h', RTGETOPT_REQ_NOTHING },
450 { "--help", 'h', RTGETOPT_REQ_NOTHING }
451 };
452 RTGETOPTSTATE GetState;
453 RTGETOPTUNION ValueUnion;
454 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
455 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
456 if (a->argc == iFirst)
457 {
458 RTPrintf(("Empty command parameter list, show help.\n"));
459 printHelp(g_pStdOut);
460 return RTEXITCODE_SUCCESS;
461 }
462
463 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
464 Utf8Str strIfaceName;
465
466 int c;
467 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
468 {
469 switch (c)
470 {
471 case 'f':
472 {
473 if (strIfaceName.isNotEmpty())
474 return errorArgument("Duplicate parameter: --ifacename");
475
476 strIfaceName = ValueUnion.psz;
477 if (strIfaceName.isEmpty())
478 return errorArgument("Empty parameter: --ifacename");
479
480 break;
481 }
482 case 'h':
483 printHelp(g_pStdOut);
484 return RTEXITCODE_SUCCESS;
485 case VINF_GETOPT_NOT_OPTION:
486 return errorUnknownSubcommand(ValueUnion.psz);
487
488 default:
489 return errorGetOpt(c, &ValueUnion);
490 }
491 }
492
493 map <com::Utf8Str, supIfaces_T>::const_iterator cIt = mapInterfaceNameToEnum.find(strIfaceName);
494 if (cIt != mapInterfaceNameToEnum.end())
495 {
496 com::SafeArray<BSTR> ObjIDsList;
497 hrc = pVirtualBox->GetTrackedObjectIds(Bstr(strIfaceName).raw(), ComSafeArrayAsOutParam(ObjIDsList));
498 if (SUCCEEDED(hrc))
499 {
500 RTPrintf(("Tracked objects IIDs:\n"));
501 for (size_t i = 0; i < ObjIDsList.size(); ++i)
502 {
503 Bstr bstrObjId = ObjIDsList[i];
504 RTPrintf((" %s\n"), Utf8Str(bstrObjId).c_str());
505 }
506 }
507 }
508
509 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
510}
511
512RTEXITCODE handleTrackedObjects(HandlerArg *a)
513{
514 enum
515 {
516 kObjectTracker_Ifaces = 1000,
517 kObjectTracker_ObjList,
518 kObjectTracker_ObjInfo,
519 };
520
521 static const RTGETOPTDEF s_aOptions[] =
522 {
523 /* common options */
524 { "ifaces", kObjectTracker_Ifaces, RTGETOPT_REQ_NOTHING },
525 { "objlist", kObjectTracker_ObjList, RTGETOPT_REQ_NOTHING },
526 { "objinfo", kObjectTracker_ObjInfo, RTGETOPT_REQ_NOTHING },
527 };
528
529 if (a->argc < 1)
530 return errorNoSubcommand();
531
532 RTGETOPTSTATE GetState;
533 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
534 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
535
536 int c;
537 RTGETOPTUNION ValueUnion;
538 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
539 {
540 switch (c)
541 {
542 /* Sub-commands: */
543 case kObjectTracker_Ifaces:
544 setCurrentSubcommand(HELP_SCOPE_OBJTRACKER_IFACES);
545 return handleSupIfaceList(a, GetState.iNext);
546 case kObjectTracker_ObjList:
547 setCurrentSubcommand(HELP_SCOPE_OBJTRACKER_OBJLIST);
548 return handleObjectList(a, GetState.iNext);
549 case kObjectTracker_ObjInfo:
550 setCurrentSubcommand(HELP_SCOPE_OBJTRACKER_OBJINFO);
551 return handleObjInfo(a, GetState.iNext);
552 case VINF_GETOPT_NOT_OPTION:
553 return errorUnknownSubcommand(ValueUnion.psz);
554 default:
555 return errorGetOpt(c, &ValueUnion);
556 }
557 }
558
559 return errorNoSubcommand();
560}
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