VirtualBox

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

Last change on this file since 78412 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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