VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp@ 94203

Last change on this file since 94203 was 94181, checked in by vboxsync, 3 years ago

doc/manual,FE/VBoxManage: Convert bandwidthctl command to refentry documentation, bugref:9186

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1/* $Id: VBoxManageBandwidthControl.cpp 94181 2022-03-11 16:55:03Z vboxsync $ */
2/** @file
3 * VBoxManage - The bandwidth control related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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#ifndef VBOX_ONLY_DOCS
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#include <VBox/com/com.h>
25#include <VBox/com/array.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/errorprint.h>
28#include <VBox/com/VirtualBox.h>
29
30#include <iprt/err.h>
31#include <iprt/path.h>
32#include <iprt/param.h>
33#include <iprt/string.h>
34#include <iprt/ctype.h>
35#include <iprt/stream.h>
36#include <iprt/getopt.h>
37#include <VBox/log.h>
38
39#include "VBoxManage.h"
40using namespace com;
41
42DECLARE_TRANSLATION_CONTEXT(BWControl);
43
44// funcs
45///////////////////////////////////////////////////////////////////////////////
46
47
48/**
49 * Parses a string in the following format "n[k|m|g|K|M|G]". Stores the value
50 * of n expressed in bytes to *pLimit. k meas kilobit, while K means kilobyte.
51 *
52 * @returns Error message or NULL if successful.
53 * @param pcszLimit The string to parse.
54 * @param pLimit Where to store the result.
55 */
56static const char *parseLimit(const char *pcszLimit, int64_t *pLimit)
57{
58 int iMultiplier = _1M;
59 char *pszNext = NULL;
60 int rc = RTStrToInt64Ex(pcszLimit, &pszNext, 10, pLimit);
61
62 switch (rc)
63 {
64 case VINF_SUCCESS:
65 break;
66 case VWRN_NUMBER_TOO_BIG:
67 return BWControl::tr("Limit is too big\n");
68 case VWRN_TRAILING_CHARS:
69 switch (*pszNext)
70 {
71 case 'G': iMultiplier = _1G; break;
72 case 'M': iMultiplier = _1M; break;
73 case 'K': iMultiplier = _1K; break;
74 case 'g': iMultiplier = 125000000; break;
75 case 'm': iMultiplier = 125000; break;
76 case 'k': iMultiplier = 125; break;
77 default: return BWControl::tr("Invalid unit suffix. Valid suffixes are: k, m, g, K, M, G\n");
78 }
79 break;
80 case VWRN_TRAILING_SPACES:
81 return BWControl::tr("Trailing spaces in limit!\n");
82 case VERR_NO_DIGITS:
83 return BWControl::tr("No digits in limit specifier\n");
84 default:
85 return BWControl::tr("Invalid limit specifier\n");
86 }
87 if (*pLimit < 0)
88 return BWControl::tr("Limit cannot be negative\n");
89 if (*pLimit > INT64_MAX / iMultiplier)
90 return BWControl::tr("Limit is too big\n");
91 *pLimit *= iMultiplier;
92
93 return NULL;
94}
95
96/**
97 * Handles the 'bandwidthctl myvm add' sub-command.
98 * @returns Exit code.
99 * @param a The handler argument package.
100 * @param bwCtrl Reference to the bandwidth control interface.
101 */
102static RTEXITCODE handleBandwidthControlAdd(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl)
103{
104 HRESULT rc = S_OK;
105 static const RTGETOPTDEF g_aBWCtlAddOptions[] =
106 {
107 { "--type", 't', RTGETOPT_REQ_STRING },
108 { "--limit", 'l', RTGETOPT_REQ_STRING }
109 };
110
111 setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_ADD);
112
113 Bstr name(a->argv[2]);
114 if (name.isEmpty())
115 {
116 errorArgument(BWControl::tr("Bandwidth group name must not be empty!\n"));
117 return RTEXITCODE_FAILURE;
118 }
119
120 const char *pszType = NULL;
121 int64_t cMaxBytesPerSec = INT64_MAX;
122
123 int c;
124 RTGETOPTUNION ValueUnion;
125 RTGETOPTSTATE GetState;
126 RTGetOptInit(&GetState, a->argc, a->argv, g_aBWCtlAddOptions,
127 RT_ELEMENTS(g_aBWCtlAddOptions), 3, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
128
129 while ( SUCCEEDED(rc)
130 && (c = RTGetOpt(&GetState, &ValueUnion)))
131 {
132 switch (c)
133 {
134 case 't': // bandwidth group type
135 {
136 if (ValueUnion.psz)
137 pszType = ValueUnion.psz;
138 else
139 rc = E_FAIL;
140 break;
141 }
142
143 case 'l': // limit
144 {
145 if (ValueUnion.psz)
146 {
147 const char *pcszError = parseLimit(ValueUnion.psz, &cMaxBytesPerSec);
148 if (pcszError)
149 {
150 errorArgument(pcszError);
151 return RTEXITCODE_FAILURE;
152 }
153 }
154 else
155 rc = E_FAIL;
156 break;
157 }
158
159 default:
160 {
161 errorGetOpt(c, &ValueUnion);
162 rc = E_FAIL;
163 break;
164 }
165 }
166 }
167
168 BandwidthGroupType_T enmType;
169
170 if (!RTStrICmp(pszType, "disk"))
171 enmType = BandwidthGroupType_Disk;
172 else if (!RTStrICmp(pszType, "network"))
173 enmType = BandwidthGroupType_Network;
174 else
175 {
176 errorArgument(BWControl::tr("Invalid bandwidth group type\n"));
177 return RTEXITCODE_FAILURE;
178 }
179
180 CHECK_ERROR2I_RET(bwCtrl, CreateBandwidthGroup(name.raw(), enmType, (LONG64)cMaxBytesPerSec), RTEXITCODE_FAILURE);
181
182 return RTEXITCODE_SUCCESS;
183}
184
185/**
186 * Handles the 'bandwidthctl myvm set' sub-command.
187 * @returns Exit code.
188 * @param a The handler argument package.
189 * @param bwCtrl Reference to the bandwidth control interface.
190 */
191static RTEXITCODE handleBandwidthControlSet(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl)
192{
193 HRESULT rc = S_OK;
194 static const RTGETOPTDEF g_aBWCtlAddOptions[] =
195 {
196 { "--limit", 'l', RTGETOPT_REQ_STRING }
197 };
198
199 setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_SET);
200
201 Bstr name(a->argv[2]);
202 int64_t cMaxBytesPerSec = INT64_MAX;
203
204 int c;
205 RTGETOPTUNION ValueUnion;
206 RTGETOPTSTATE GetState;
207 RTGetOptInit(&GetState, a->argc, a->argv, g_aBWCtlAddOptions,
208 RT_ELEMENTS(g_aBWCtlAddOptions), 3, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
209
210 while ( SUCCEEDED(rc)
211 && (c = RTGetOpt(&GetState, &ValueUnion)))
212 {
213 switch (c)
214 {
215 case 'l': // limit
216 {
217 if (ValueUnion.psz)
218 {
219 const char *pcszError = parseLimit(ValueUnion.psz, &cMaxBytesPerSec);
220 if (pcszError)
221 {
222 errorArgument(pcszError);
223 return RTEXITCODE_FAILURE;
224 }
225 }
226 else
227 rc = E_FAIL;
228 break;
229 }
230
231 default:
232 {
233 errorGetOpt(c, &ValueUnion);
234 rc = E_FAIL;
235 break;
236 }
237 }
238 }
239
240
241 if (cMaxBytesPerSec != INT64_MAX)
242 {
243 ComPtr<IBandwidthGroup> bwGroup;
244 CHECK_ERROR2I_RET(bwCtrl, GetBandwidthGroup(name.raw(), bwGroup.asOutParam()), RTEXITCODE_FAILURE);
245 if (SUCCEEDED(rc))
246 {
247 CHECK_ERROR2I_RET(bwGroup, COMSETTER(MaxBytesPerSec)((LONG64)cMaxBytesPerSec), RTEXITCODE_FAILURE);
248 }
249 }
250
251 return RTEXITCODE_SUCCESS;
252}
253
254/**
255 * Handles the 'bandwidthctl myvm remove' sub-command.
256 * @returns Exit code.
257 * @param a The handler argument package.
258 * @param bwCtrl Reference to the bandwidth control interface.
259 */
260static RTEXITCODE handleBandwidthControlRemove(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl)
261{
262 setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_REMOVE);
263
264 Bstr name(a->argv[2]);
265 CHECK_ERROR2I_RET(bwCtrl, DeleteBandwidthGroup(name.raw()), RTEXITCODE_FAILURE);
266 return RTEXITCODE_SUCCESS;
267}
268
269/**
270 * Handles the 'bandwidthctl myvm list' sub-command.
271 * @returns Exit code.
272 * @param a The handler argument package.
273 * @param bwCtrl Reference to the bandwidth control interface.
274 */
275static RTEXITCODE handleBandwidthControlList(HandlerArg *pArgs, ComPtr<IBandwidthControl> &rptrBWControl)
276{
277 static const RTGETOPTDEF g_aOptions[] =
278 {
279 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
280 };
281
282 setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_LIST);
283 VMINFO_DETAILS enmDetails = VMINFO_STANDARD;
284
285 int c;
286 RTGETOPTUNION ValueUnion;
287 RTGETOPTSTATE GetState;
288 RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, g_aOptions, RT_ELEMENTS(g_aOptions), 2 /*iArg*/, 0 /*fFlags*/);
289 while ((c = RTGetOpt(&GetState, &ValueUnion)))
290 {
291 switch (c)
292 {
293 case 'M':
294 enmDetails = VMINFO_MACHINEREADABLE;
295 break;
296 default:
297 return errorGetOpt(c, &ValueUnion);
298 }
299 }
300
301 if (FAILED(showBandwidthGroups(rptrBWControl, enmDetails)))
302 return RTEXITCODE_FAILURE;
303
304 return RTEXITCODE_SUCCESS;
305}
306
307
308/**
309 * Handles the 'bandwidthctl' command.
310 * @returns Exit code.
311 * @param a The handler argument package.
312 */
313RTEXITCODE handleBandwidthControl(HandlerArg *a)
314{
315 HRESULT rc = S_OK;
316 ComPtr<IMachine> machine;
317 ComPtr<IBandwidthControl> bwCtrl;
318
319 if (a->argc < 2)
320 return errorSyntax(BWControl::tr("Too few parameters"));
321 else if (a->argc > 7)
322 return errorSyntax(BWControl::tr("Too many parameters"));
323
324 /* try to find the given machine */
325 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
326 machine.asOutParam()), RTEXITCODE_FAILURE);
327
328 /* open a session for the VM (new or shared) */
329 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE);
330 SessionType_T st;
331 CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), RTEXITCODE_FAILURE);
332 bool fRunTime = (st == SessionType_Shared);
333
334 /* get the mutable session machine */
335 a->session->COMGETTER(Machine)(machine.asOutParam());
336 rc = machine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam());
337 if (FAILED(rc)) goto leave;
338
339 if (!strcmp(a->argv[1], "add"))
340 {
341 if (fRunTime)
342 {
343 errorArgument(BWControl::tr("Bandwidth groups cannot be created while the VM is running\n"));
344 goto leave;
345 }
346 rc = handleBandwidthControlAdd(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
347 }
348 else if (!strcmp(a->argv[1], "remove"))
349 {
350 if (fRunTime)
351 {
352 errorArgument(BWControl::tr("Bandwidth groups cannot be deleted while the VM is running\n"));
353 goto leave;
354 }
355 rc = handleBandwidthControlRemove(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
356 }
357 else if (!strcmp(a->argv[1], "set"))
358 rc = handleBandwidthControlSet(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
359 else if (!strcmp(a->argv[1], "list"))
360 rc = handleBandwidthControlList(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
361 else
362 {
363 errorSyntax(BWControl::tr("Invalid parameter '%s'"), a->argv[1]);
364 rc = E_FAIL;
365 }
366
367 /* commit changes */
368 if (SUCCEEDED(rc))
369 CHECK_ERROR(machine, SaveSettings());
370
371leave:
372 /* it's important to always close sessions */
373 a->session->UnlockMachine();
374
375 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
376}
377
378#endif /* !VBOX_ONLY_DOCS */
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