VirtualBox

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

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