VirtualBox

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

Last change on this file since 92710 was 92372, checked in by vboxsync, 3 years ago

Main: bugref:1909: Added translation marks around messages of VBoxManage output

  • 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 92372 2021-11-11 14:45:18Z vboxsync $ */
2/** @file
3 * VBoxManage - The bandwidth control related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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
112 Bstr name(a->argv[2]);
113 if (name.isEmpty())
114 {
115 errorArgument(BWControl::tr("Bandwidth group name must not be empty!\n"));
116 return RTEXITCODE_FAILURE;
117 }
118
119 const char *pszType = NULL;
120 int64_t cMaxBytesPerSec = INT64_MAX;
121
122 int c;
123 RTGETOPTUNION ValueUnion;
124 RTGETOPTSTATE GetState;
125 RTGetOptInit(&GetState, a->argc, a->argv, g_aBWCtlAddOptions,
126 RT_ELEMENTS(g_aBWCtlAddOptions), 3, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
127
128 while ( SUCCEEDED(rc)
129 && (c = RTGetOpt(&GetState, &ValueUnion)))
130 {
131 switch (c)
132 {
133 case 't': // bandwidth group type
134 {
135 if (ValueUnion.psz)
136 pszType = ValueUnion.psz;
137 else
138 rc = E_FAIL;
139 break;
140 }
141
142 case 'l': // limit
143 {
144 if (ValueUnion.psz)
145 {
146 const char *pcszError = parseLimit(ValueUnion.psz, &cMaxBytesPerSec);
147 if (pcszError)
148 {
149 errorArgument(pcszError);
150 return RTEXITCODE_FAILURE;
151 }
152 }
153 else
154 rc = E_FAIL;
155 break;
156 }
157
158 default:
159 {
160 errorGetOpt(USAGE_BANDWIDTHCONTROL, c, &ValueUnion);
161 rc = E_FAIL;
162 break;
163 }
164 }
165 }
166
167 BandwidthGroupType_T enmType;
168
169 if (!RTStrICmp(pszType, "disk"))
170 enmType = BandwidthGroupType_Disk;
171 else if (!RTStrICmp(pszType, "network"))
172 enmType = BandwidthGroupType_Network;
173 else
174 {
175 errorArgument(BWControl::tr("Invalid bandwidth group type\n"));
176 return RTEXITCODE_FAILURE;
177 }
178
179 CHECK_ERROR2I_RET(bwCtrl, CreateBandwidthGroup(name.raw(), enmType, (LONG64)cMaxBytesPerSec), RTEXITCODE_FAILURE);
180
181 return RTEXITCODE_SUCCESS;
182}
183
184/**
185 * Handles the 'bandwidthctl myvm set' sub-command.
186 * @returns Exit code.
187 * @param a The handler argument package.
188 * @param bwCtrl Reference to the bandwidth control interface.
189 */
190static RTEXITCODE handleBandwidthControlSet(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl)
191{
192 HRESULT rc = S_OK;
193 static const RTGETOPTDEF g_aBWCtlAddOptions[] =
194 {
195 { "--limit", 'l', RTGETOPT_REQ_STRING }
196 };
197
198
199 Bstr name(a->argv[2]);
200 int64_t cMaxBytesPerSec = INT64_MAX;
201
202 int c;
203 RTGETOPTUNION ValueUnion;
204 RTGETOPTSTATE GetState;
205 RTGetOptInit(&GetState, a->argc, a->argv, g_aBWCtlAddOptions,
206 RT_ELEMENTS(g_aBWCtlAddOptions), 3, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
207
208 while ( SUCCEEDED(rc)
209 && (c = RTGetOpt(&GetState, &ValueUnion)))
210 {
211 switch (c)
212 {
213 case 'l': // limit
214 {
215 if (ValueUnion.psz)
216 {
217 const char *pcszError = parseLimit(ValueUnion.psz, &cMaxBytesPerSec);
218 if (pcszError)
219 {
220 errorArgument(pcszError);
221 return RTEXITCODE_FAILURE;
222 }
223 }
224 else
225 rc = E_FAIL;
226 break;
227 }
228
229 default:
230 {
231 errorGetOpt(USAGE_BANDWIDTHCONTROL, c, &ValueUnion);
232 rc = E_FAIL;
233 break;
234 }
235 }
236 }
237
238
239 if (cMaxBytesPerSec != INT64_MAX)
240 {
241 ComPtr<IBandwidthGroup> bwGroup;
242 CHECK_ERROR2I_RET(bwCtrl, GetBandwidthGroup(name.raw(), bwGroup.asOutParam()), RTEXITCODE_FAILURE);
243 if (SUCCEEDED(rc))
244 {
245 CHECK_ERROR2I_RET(bwGroup, COMSETTER(MaxBytesPerSec)((LONG64)cMaxBytesPerSec), RTEXITCODE_FAILURE);
246 }
247 }
248
249 return RTEXITCODE_SUCCESS;
250}
251
252/**
253 * Handles the 'bandwidthctl myvm remove' sub-command.
254 * @returns Exit code.
255 * @param a The handler argument package.
256 * @param bwCtrl Reference to the bandwidth control interface.
257 */
258static RTEXITCODE handleBandwidthControlRemove(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl)
259{
260 Bstr name(a->argv[2]);
261 CHECK_ERROR2I_RET(bwCtrl, DeleteBandwidthGroup(name.raw()), RTEXITCODE_FAILURE);
262 return RTEXITCODE_SUCCESS;
263}
264
265/**
266 * Handles the 'bandwidthctl myvm list' sub-command.
267 * @returns Exit code.
268 * @param a The handler argument package.
269 * @param bwCtrl Reference to the bandwidth control interface.
270 */
271static RTEXITCODE handleBandwidthControlList(HandlerArg *pArgs, ComPtr<IBandwidthControl> &rptrBWControl)
272{
273 static const RTGETOPTDEF g_aOptions[] =
274 {
275 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
276 };
277
278 VMINFO_DETAILS enmDetails = VMINFO_STANDARD;
279
280 int c;
281 RTGETOPTUNION ValueUnion;
282 RTGETOPTSTATE GetState;
283 RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, g_aOptions, RT_ELEMENTS(g_aOptions), 2 /*iArg*/, 0 /*fFlags*/);
284 while ((c = RTGetOpt(&GetState, &ValueUnion)))
285 {
286 switch (c)
287 {
288 case 'M':
289 enmDetails = VMINFO_MACHINEREADABLE;
290 break;
291 default:
292 return errorGetOpt(USAGE_BANDWIDTHCONTROL, c, &ValueUnion);
293 }
294 }
295
296 if (FAILED(showBandwidthGroups(rptrBWControl, enmDetails)))
297 return RTEXITCODE_FAILURE;
298
299 return RTEXITCODE_SUCCESS;
300}
301
302
303/**
304 * Handles the 'bandwidthctl' command.
305 * @returns Exit code.
306 * @param a The handler argument package.
307 */
308RTEXITCODE handleBandwidthControl(HandlerArg *a)
309{
310 HRESULT rc = S_OK;
311 ComPtr<IMachine> machine;
312 ComPtr<IBandwidthControl> bwCtrl;
313
314 if (a->argc < 2)
315 return errorSyntax(USAGE_BANDWIDTHCONTROL, BWControl::tr("Too few parameters"));
316 else if (a->argc > 7)
317 return errorSyntax(USAGE_BANDWIDTHCONTROL, BWControl::tr("Too many parameters"));
318
319 /* try to find the given machine */
320 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
321 machine.asOutParam()), RTEXITCODE_FAILURE);
322
323 /* open a session for the VM (new or shared) */
324 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE);
325 SessionType_T st;
326 CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), RTEXITCODE_FAILURE);
327 bool fRunTime = (st == SessionType_Shared);
328
329 /* get the mutable session machine */
330 a->session->COMGETTER(Machine)(machine.asOutParam());
331 rc = machine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam());
332 if (FAILED(rc)) goto leave;
333
334 if (!strcmp(a->argv[1], "add"))
335 {
336 if (fRunTime)
337 {
338 errorArgument(BWControl::tr("Bandwidth groups cannot be created while the VM is running\n"));
339 goto leave;
340 }
341 rc = handleBandwidthControlAdd(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
342 }
343 else if (!strcmp(a->argv[1], "remove"))
344 {
345 if (fRunTime)
346 {
347 errorArgument(BWControl::tr("Bandwidth groups cannot be deleted while the VM is running\n"));
348 goto leave;
349 }
350 rc = handleBandwidthControlRemove(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
351 }
352 else if (!strcmp(a->argv[1], "set"))
353 rc = handleBandwidthControlSet(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
354 else if (!strcmp(a->argv[1], "list"))
355 rc = handleBandwidthControlList(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
356 else
357 {
358 errorSyntax(USAGE_BANDWIDTHCONTROL, BWControl::tr("Invalid parameter '%s'"), Utf8Str(a->argv[1]).c_str());
359 rc = E_FAIL;
360 }
361
362 /* commit changes */
363 if (SUCCEEDED(rc))
364 CHECK_ERROR(machine, SaveSettings());
365
366leave:
367 /* it's important to always close sessions */
368 a->session->UnlockMachine();
369
370 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
371}
372
373#endif /* !VBOX_ONLY_DOCS */
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