VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp@ 29970

Last change on this file since 29970 was 29970, checked in by vboxsync, 15 years ago

pause before savestate to avoid a live save

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.1 KB
Line 
1/* $Id: VBoxManageControlVM.cpp 29970 2010-06-02 08:46:23Z vboxsync $ */
2/** @file
3 * VBoxManage - VirtualBox's command-line interface.
4 */
5
6/*
7 * Copyright (C) 2006-2009 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
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <VBox/com/com.h>
23#include <VBox/com/string.h>
24#include <VBox/com/Guid.h>
25#include <VBox/com/array.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/errorprint.h>
28#include <VBox/com/EventQueue.h>
29
30#include <VBox/com/VirtualBox.h>
31
32#include <iprt/ctype.h>
33#include <VBox/err.h>
34#include <iprt/getopt.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <iprt/uuid.h>
38#include <VBox/log.h>
39
40#include "VBoxManage.h"
41
42
43/**
44 * Parses a number.
45 *
46 * @returns Valid number on success.
47 * @returns 0 if invalid number. All necesary bitching has been done.
48 * @param psz Pointer to the nic number.
49 */
50static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
51{
52 uint32_t u32;
53 char *pszNext;
54 int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
55 if ( RT_SUCCESS(rc)
56 && *pszNext == '\0'
57 && u32 >= 1
58 && u32 <= cMaxNum)
59 return (unsigned)u32;
60 errorArgument("Invalid %s number '%s'", name, psz);
61 return 0;
62}
63
64
65int handleControlVM(HandlerArg *a)
66{
67 using namespace com;
68 HRESULT rc;
69
70 if (a->argc < 2)
71 return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
72
73 /* try to find the given machine */
74 ComPtr <IMachine> machine;
75 Bstr machineuuid (a->argv[0]);
76 if (!Guid(machineuuid).isEmpty())
77 {
78 CHECK_ERROR(a->virtualBox, GetMachine(machineuuid, machine.asOutParam()));
79 }
80 else
81 {
82 CHECK_ERROR(a->virtualBox, FindMachine(machineuuid, machine.asOutParam()));
83 if (SUCCEEDED (rc))
84 machine->COMGETTER(Id)(machineuuid.asOutParam());
85 }
86 if (FAILED (rc))
87 return 1;
88
89 /* open a session for the VM */
90 CHECK_ERROR_RET(a->virtualBox, OpenExistingSession(a->session, machineuuid), 1);
91
92 do
93 {
94 /* get the associated console */
95 ComPtr<IConsole> console;
96 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
97 /* ... and session machine */
98 ComPtr<IMachine> sessionMachine;
99 CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
100
101 /* which command? */
102 if (!strcmp(a->argv[1], "pause"))
103 {
104 CHECK_ERROR_BREAK(console, Pause());
105 }
106 else if (!strcmp(a->argv[1], "resume"))
107 {
108 CHECK_ERROR_BREAK(console, Resume());
109 }
110 else if (!strcmp(a->argv[1], "reset"))
111 {
112 CHECK_ERROR_BREAK(console, Reset());
113 }
114 else if (!strcmp(a->argv[1], "unplugcpu"))
115 {
116 if (a->argc <= 1 + 1)
117 {
118 errorArgument("Missing argument to '%s'. Expected CPU number.", a->argv[1]);
119 rc = E_FAIL;
120 break;
121 }
122
123 unsigned n = parseNum(a->argv[2], 32, "CPU");
124
125 CHECK_ERROR_BREAK(sessionMachine, HotUnplugCPU(n));
126 }
127 else if (!strcmp(a->argv[1], "plugcpu"))
128 {
129 if (a->argc <= 1 + 1)
130 {
131 errorArgument("Missing argument to '%s'. Expected CPU number.", a->argv[1]);
132 rc = E_FAIL;
133 break;
134 }
135
136 unsigned n = parseNum(a->argv[2], 32, "CPU");
137
138 CHECK_ERROR_BREAK(sessionMachine, HotPlugCPU(n));
139 }
140 else if (!strcmp(a->argv[1], "poweroff"))
141 {
142 ComPtr<IProgress> progress;
143 CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
144
145 rc = showProgress(progress);
146 if (FAILED(rc))
147 {
148 com::ProgressErrorInfo info(progress);
149 if (info.isBasicAvailable())
150 {
151 RTPrintf("Error: failed to power off machine. Error message: %lS\n", info.getText().raw());
152 }
153 else
154 {
155 RTPrintf("Error: failed to power off machine. No error message available!\n");
156 }
157 }
158 }
159 else if (!strcmp(a->argv[1], "savestate"))
160 {
161 /* first pause so we don't trigger a live save which needs more time/resources */
162 CHECK_ERROR_BREAK(console, Pause());
163
164 ComPtr<IProgress> progress;
165 CHECK_ERROR_BREAK(console, SaveState(progress.asOutParam()));
166
167 rc = showProgress(progress);
168 if (FAILED(rc))
169 {
170 com::ProgressErrorInfo info(progress);
171 if (info.isBasicAvailable())
172 {
173 RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
174 }
175 else
176 {
177 RTPrintf("Error: failed to save machine state. No error message available!\n");
178 }
179 }
180 }
181 else if (!strcmp(a->argv[1], "acpipowerbutton"))
182 {
183 CHECK_ERROR_BREAK(console, PowerButton());
184 }
185 else if (!strcmp(a->argv[1], "acpisleepbutton"))
186 {
187 CHECK_ERROR_BREAK(console, SleepButton());
188 }
189 else if (!strcmp(a->argv[1], "injectnmi"))
190 {
191 /* get the machine debugger. */
192 ComPtr <IMachineDebugger> debugger;
193 CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));
194 CHECK_ERROR_BREAK(debugger, InjectNMI());
195 }
196 else if (!strcmp(a->argv[1], "keyboardputscancode"))
197 {
198 ComPtr<IKeyboard> keyboard;
199 CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
200
201 if (a->argc <= 1 + 1)
202 {
203 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", a->argv[1]);
204 rc = E_FAIL;
205 break;
206 }
207
208 /* Arbitrary restrict the length of a sequence of scancodes to 1024. */
209 LONG alScancodes[1024];
210 int cScancodes = 0;
211
212 /* Process the command line. */
213 int i;
214 for (i = 1 + 1; i < a->argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
215 {
216 if ( RT_C_IS_XDIGIT (a->argv[i][0])
217 && RT_C_IS_XDIGIT (a->argv[i][1])
218 && a->argv[i][2] == 0)
219 {
220 uint8_t u8Scancode;
221 int irc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode);
222 if (RT_FAILURE (irc))
223 {
224 RTPrintf("Error: converting '%s' returned %Rrc!\n", a->argv[i], rc);
225 rc = E_FAIL;
226 break;
227 }
228
229 alScancodes[cScancodes] = u8Scancode;
230 }
231 else
232 {
233 RTPrintf("Error: '%s' is not a hex byte!\n", a->argv[i]);
234 rc = E_FAIL;
235 break;
236 }
237 }
238
239 if (FAILED(rc))
240 break;
241
242 if ( cScancodes == RT_ELEMENTS(alScancodes)
243 && i < a->argc)
244 {
245 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
246 rc = E_FAIL;
247 break;
248 }
249
250 /* Send scancodes to the VM.
251 * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
252 */
253 for (i = 0; i < cScancodes; i++)
254 {
255 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
256 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
257 }
258 }
259 else if (!strncmp(a->argv[1], "setlinkstate", 12))
260 {
261 /* Get the number of network adapters */
262 ULONG NetworkAdapterCount = 0;
263 ComPtr <ISystemProperties> info;
264 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
265 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
266
267 unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
268 if (!n)
269 {
270 rc = E_FAIL;
271 break;
272 }
273 if (a->argc <= 1 + 1)
274 {
275 errorArgument("Missing argument to '%s'", a->argv[1]);
276 rc = E_FAIL;
277 break;
278 }
279 /* get the corresponding network adapter */
280 ComPtr<INetworkAdapter> adapter;
281 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
282 if (adapter)
283 {
284 if (!strcmp(a->argv[2], "on"))
285 {
286 CHECK_ERROR_BREAK(adapter, COMSETTER(CableConnected)(TRUE));
287 }
288 else if (!strcmp(a->argv[2], "off"))
289 {
290 CHECK_ERROR_BREAK(adapter, COMSETTER(CableConnected)(FALSE));
291 }
292 else
293 {
294 errorArgument("Invalid link state '%s'", Utf8Str(a->argv[2]).raw());
295 rc = E_FAIL;
296 break;
297 }
298 }
299 }
300#ifdef VBOX_DYNAMIC_NET_ATTACH
301 /* here the order in which strncmp is called is important
302 * cause nictracefile can be very well compared with
303 * nictrace and nic and thus everything will always fail
304 * if the order is changed
305 */
306 else if (!strncmp(a->argv[1], "nictracefile", 12))
307 {
308 /* Get the number of network adapters */
309 ULONG NetworkAdapterCount = 0;
310 ComPtr <ISystemProperties> info;
311 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
312 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
313
314 unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
315 if (!n)
316 {
317 rc = E_FAIL;
318 break;
319 }
320 if (a->argc <= 2)
321 {
322 errorArgument("Missing argument to '%s'", a->argv[1]);
323 rc = E_FAIL;
324 break;
325 }
326
327 /* get the corresponding network adapter */
328 ComPtr<INetworkAdapter> adapter;
329 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
330 if (adapter)
331 {
332 BOOL fEnabled;
333 adapter->COMGETTER(Enabled)(&fEnabled);
334 if (fEnabled)
335 {
336 if (a->argv[2])
337 {
338 CHECK_ERROR_RET(adapter, COMSETTER(TraceFile)(Bstr(a->argv[2])), 1);
339 }
340 else
341 {
342 errorArgument("Invalid filename or filename not specified for NIC %lu", n);
343 rc = E_FAIL;
344 break;
345 }
346 }
347 else
348 {
349 RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
350 }
351 }
352 }
353 else if (!strncmp(a->argv[1], "nictrace", 8))
354 {
355 /* Get the number of network adapters */
356 ULONG NetworkAdapterCount = 0;
357 ComPtr <ISystemProperties> info;
358 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
359 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
360
361 unsigned n = parseNum(&a->argv[1][8], NetworkAdapterCount, "NIC");
362 if (!n)
363 {
364 rc = E_FAIL;
365 break;
366 }
367 if (a->argc <= 2)
368 {
369 errorArgument("Missing argument to '%s'", a->argv[1]);
370 rc = E_FAIL;
371 break;
372 }
373
374 /* get the corresponding network adapter */
375 ComPtr<INetworkAdapter> adapter;
376 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
377 if (adapter)
378 {
379 BOOL fEnabled;
380 adapter->COMGETTER(Enabled)(&fEnabled);
381 if (fEnabled)
382 {
383 if (!strcmp(a->argv[2], "on"))
384 {
385 CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(TRUE), 1);
386 }
387 else if (!strcmp(a->argv[2], "off"))
388 {
389 CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(FALSE), 1);
390 }
391 else
392 {
393 errorArgument("Invalid nictrace%lu argument '%s'", n, Utf8Str(a->argv[2]).raw());
394 rc = E_FAIL;
395 break;
396 }
397 }
398 else
399 {
400 RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
401 }
402 }
403 }
404 else if (!strncmp(a->argv[1], "nic", 3))
405 {
406 /* Get the number of network adapters */
407 ULONG NetworkAdapterCount = 0;
408 ComPtr <ISystemProperties> info;
409 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
410 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
411
412 unsigned n = parseNum(&a->argv[1][3], NetworkAdapterCount, "NIC");
413 if (!n)
414 {
415 rc = E_FAIL;
416 break;
417 }
418 if (a->argc <= 2)
419 {
420 errorArgument("Missing argument to '%s'", a->argv[1]);
421 rc = E_FAIL;
422 break;
423 }
424
425 /* get the corresponding network adapter */
426 ComPtr<INetworkAdapter> adapter;
427 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
428 if (adapter)
429 {
430 BOOL fEnabled;
431 adapter->COMGETTER(Enabled)(&fEnabled);
432 if (fEnabled)
433 {
434 if (!strcmp(a->argv[2], "null"))
435 {
436 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
437 CHECK_ERROR_RET(adapter, Detach(), 1);
438 }
439 else if (!strcmp(a->argv[2], "nat"))
440 {
441 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
442 if (a->argc == 4)
443 CHECK_ERROR_RET(adapter, COMSETTER(NATNetwork)(Bstr(a->argv[3])), 1);
444 CHECK_ERROR_RET(adapter, AttachToNAT(), 1);
445 }
446 else if ( !strcmp(a->argv[2], "bridged")
447 || !strcmp(a->argv[2], "hostif")) /* backward compatibility */
448 {
449 if (a->argc <= 3)
450 {
451 errorArgument("Missing argument to '%s'", a->argv[2]);
452 rc = E_FAIL;
453 break;
454 }
455 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
456 CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
457 CHECK_ERROR_RET(adapter, AttachToBridgedInterface(), 1);
458 }
459 else if (!strcmp(a->argv[2], "intnet"))
460 {
461 if (a->argc <= 3)
462 {
463 errorArgument("Missing argument to '%s'", a->argv[2]);
464 rc = E_FAIL;
465 break;
466 }
467 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
468 CHECK_ERROR_RET(adapter, COMSETTER(InternalNetwork)(Bstr(a->argv[3])), 1);
469 CHECK_ERROR_RET(adapter, AttachToInternalNetwork(), 1);
470 }
471#if defined(VBOX_WITH_NETFLT)
472 else if (!strcmp(a->argv[2], "hostonly"))
473 {
474 if (a->argc <= 3)
475 {
476 errorArgument("Missing argument to '%s'", a->argv[2]);
477 rc = E_FAIL;
478 break;
479 }
480 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
481 CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
482 CHECK_ERROR_RET(adapter, AttachToHostOnlyInterface(), 1);
483 }
484#endif
485 else
486 {
487 errorArgument("Invalid type '%s' specfied for NIC %lu", Utf8Str(a->argv[2]).raw(), n);
488 rc = E_FAIL;
489 break;
490 }
491 }
492 else
493 {
494 RTPrintf("The NIC %d is currently disabled and thus can't change its attachment type\n", n);
495 }
496 }
497 }
498#endif /* VBOX_DYNAMIC_NET_ATTACH */
499#ifdef VBOX_WITH_VRDP
500 else if (!strcmp(a->argv[1], "vrdp"))
501 {
502 if (a->argc <= 1 + 1)
503 {
504 errorArgument("Missing argument to '%s'", a->argv[1]);
505 rc = E_FAIL;
506 break;
507 }
508 /* get the corresponding VRDP server */
509 ComPtr<IVRDPServer> vrdpServer;
510 sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
511 ASSERT(vrdpServer);
512 if (vrdpServer)
513 {
514 if (!strcmp(a->argv[2], "on"))
515 {
516 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Enabled)(TRUE));
517 }
518 else if (!strcmp(a->argv[2], "off"))
519 {
520 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Enabled)(FALSE));
521 }
522 else
523 {
524 errorArgument("Invalid vrdp server state '%s'", Utf8Str(a->argv[2]).raw());
525 rc = E_FAIL;
526 break;
527 }
528 }
529 }
530 else if (!strcmp(a->argv[1], "vrdpport"))
531 {
532 if (a->argc <= 1 + 1)
533 {
534 errorArgument("Missing argument to '%s'", a->argv[1]);
535 rc = E_FAIL;
536 break;
537 }
538 /* get the corresponding VRDP server */
539 ComPtr<IVRDPServer> vrdpServer;
540 sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
541 ASSERT(vrdpServer);
542 if (vrdpServer)
543 {
544 Bstr vrdpports;
545
546 if (!strcmp(a->argv[2], "default"))
547 vrdpports = "0";
548 else
549 vrdpports = a->argv [2];
550
551 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Ports)(vrdpports));
552 }
553 }
554 else if (!strcmp(a->argv[1], "vrdpvideochannelquality"))
555 {
556 if (a->argc <= 1 + 1)
557 {
558 errorArgument("Missing argument to '%s'", a->argv[1]);
559 rc = E_FAIL;
560 break;
561 }
562 /* get the corresponding VRDP server */
563 ComPtr<IVRDPServer> vrdpServer;
564 sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
565 ASSERT(vrdpServer);
566 if (vrdpServer)
567 {
568 unsigned n = parseNum(a->argv[2], 100, "VRDP video channel quality in percent");
569
570 CHECK_ERROR(vrdpServer, COMSETTER(VideoChannelQuality)(n));
571 }
572 }
573#endif /* VBOX_WITH_VRDP */
574 else if ( !strcmp(a->argv[1], "usbattach")
575 || !strcmp(a->argv[1], "usbdetach"))
576 {
577 if (a->argc < 3)
578 {
579 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
580 rc = E_FAIL;
581 break;
582 }
583
584 bool attach = !strcmp(a->argv[1], "usbattach");
585
586 Bstr usbId = a->argv [2];
587 if (Guid(usbId).isEmpty())
588 {
589 // assume address
590 if (attach)
591 {
592 ComPtr <IHost> host;
593 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
594 SafeIfaceArray <IHostUSBDevice> coll;
595 CHECK_ERROR_BREAK(host, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
596 ComPtr <IHostUSBDevice> dev;
597 CHECK_ERROR_BREAK(host, FindUSBDeviceByAddress(Bstr(a->argv [2]), dev.asOutParam()));
598 CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
599 }
600 else
601 {
602 SafeIfaceArray <IUSBDevice> coll;
603 CHECK_ERROR_BREAK(console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
604 ComPtr <IUSBDevice> dev;
605 CHECK_ERROR_BREAK(console, FindUSBDeviceByAddress(Bstr(a->argv [2]),
606 dev.asOutParam()));
607 CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
608 }
609 }
610
611 if (attach)
612 CHECK_ERROR_BREAK(console, AttachUSBDevice(usbId));
613 else
614 {
615 ComPtr <IUSBDevice> dev;
616 CHECK_ERROR_BREAK(console, DetachUSBDevice(usbId, dev.asOutParam()));
617 }
618 }
619 else if (!strcmp(a->argv[1], "setvideomodehint"))
620 {
621 if (a->argc != 5 && a->argc != 6)
622 {
623 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
624 rc = E_FAIL;
625 break;
626 }
627 uint32_t xres = RTStrToUInt32(a->argv[2]);
628 uint32_t yres = RTStrToUInt32(a->argv[3]);
629 uint32_t bpp = RTStrToUInt32(a->argv[4]);
630 uint32_t displayIdx = 0;
631 if (a->argc == 6)
632 displayIdx = RTStrToUInt32(a->argv[5]);
633
634 ComPtr<IDisplay> display;
635 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
636 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
637 }
638 else if (!strcmp(a->argv[1], "setcredentials"))
639 {
640 bool fAllowLocalLogon = true;
641 if (a->argc == 7)
642 {
643 if ( strcmp(a->argv[5], "--allowlocallogon")
644 && strcmp(a->argv[5], "-allowlocallogon"))
645 {
646 errorArgument("Invalid parameter '%s'", a->argv[5]);
647 rc = E_FAIL;
648 break;
649 }
650 if (!strcmp(a->argv[6], "no"))
651 fAllowLocalLogon = false;
652 }
653 else if (a->argc != 5)
654 {
655 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
656 rc = E_FAIL;
657 break;
658 }
659
660 ComPtr<IGuest> guest;
661 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
662 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
663 }
664#if 0 /* TODO: review & remove */
665 else if (!strcmp(a->argv[1], "dvdattach"))
666 {
667 Bstr uuid;
668 if (a->argc != 3)
669 {
670 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
671 rc = E_FAIL;
672 break;
673 }
674
675 ComPtr<IMedium> dvdMedium;
676
677 /* unmount? */
678 if (!strcmp(a->argv[2], "none"))
679 {
680 /* nothing to do, NULL object will cause unmount */
681 }
682 /* host drive? */
683 else if (!strncmp(a->argv[2], "host:", 5))
684 {
685 ComPtr<IHost> host;
686 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
687
688 rc = host->FindHostDVDDrive(Bstr(a->argv[2] + 5), dvdMedium.asOutParam());
689 if (!dvdMedium)
690 {
691 errorArgument("Invalid host DVD drive name \"%s\"",
692 a->argv[2] + 5);
693 rc = E_FAIL;
694 break;
695 }
696 }
697 else
698 {
699 /* first assume it's a UUID */
700 uuid = a->argv[2];
701 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
702 if (FAILED(rc) || !dvdMedium)
703 {
704 /* must be a filename, check if it's in the collection */
705 rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdMedium.asOutParam());
706 /* not registered, do that on the fly */
707 if (!dvdMedium)
708 {
709 Bstr emptyUUID;
710 CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdMedium.asOutParam()));
711 }
712 }
713 if (!dvdMedium)
714 {
715 rc = E_FAIL;
716 break;
717 }
718 }
719
720 /** @todo generalize this, allow arbitrary number of DVD drives
721 * and as a consequence multiple attachments and different
722 * storage controllers. */
723 if (dvdMedium)
724 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
725 else
726 uuid = Guid().toString();
727 CHECK_ERROR(machine, MountMedium(Bstr("IDE Controller"), 1, 0, uuid, FALSE /* aForce */));
728 }
729 else if (!strcmp(a->argv[1], "floppyattach"))
730 {
731 Bstr uuid;
732 if (a->argc != 3)
733 {
734 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
735 rc = E_FAIL;
736 break;
737 }
738
739 ComPtr<IMedium> floppyMedium;
740
741 /* unmount? */
742 if (!strcmp(a->argv[2], "none"))
743 {
744 /* nothing to do, NULL object will cause unmount */
745 }
746 /* host drive? */
747 else if (!strncmp(a->argv[2], "host:", 5))
748 {
749 ComPtr<IHost> host;
750 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
751 host->FindHostFloppyDrive(Bstr(a->argv[2] + 5), floppyMedium.asOutParam());
752 if (!floppyMedium)
753 {
754 errorArgument("Invalid host floppy drive name \"%s\"",
755 a->argv[2] + 5);
756 rc = E_FAIL;
757 break;
758 }
759 }
760 else
761 {
762 /* first assume it's a UUID */
763 uuid = a->argv[2];
764 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
765 if (FAILED(rc) || !floppyMedium)
766 {
767 /* must be a filename, check if it's in the collection */
768 rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyMedium.asOutParam());
769 /* not registered, do that on the fly */
770 if (!floppyMedium)
771 {
772 Bstr emptyUUID;
773 CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyMedium.asOutParam()));
774 }
775 }
776 if (!floppyMedium)
777 {
778 rc = E_FAIL;
779 break;
780 }
781 }
782 floppyMedium->COMGETTER(Id)(uuid.asOutParam());
783 CHECK_ERROR(machine, MountMedium(Bstr("Floppy Controller"), 0, 0, uuid, FALSE /* aForce */));
784 }
785#endif /* obsolete dvdattach/floppyattach */
786 else if (!strcmp(a->argv[1], "guestmemoryballoon"))
787 {
788 if (a->argc != 3)
789 {
790 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
791 rc = E_FAIL;
792 break;
793 }
794 uint32_t uVal;
795 int vrc;
796 vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
797 if (vrc != VINF_SUCCESS)
798 {
799 errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
800 rc = E_FAIL;
801 break;
802 }
803 /* guest is running; update IGuest */
804 ComPtr <IGuest> guest;
805 rc = console->COMGETTER(Guest)(guest.asOutParam());
806 if (SUCCEEDED(rc))
807 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
808 }
809 else if (!strcmp(a->argv[1], "teleport"))
810 {
811 Bstr bstrHostname;
812 uint32_t uMaxDowntime = 250 /*ms*/;
813 uint32_t uPort = UINT32_MAX;
814 uint32_t cMsTimeout = 0;
815 Bstr bstrPassword("");
816 static const RTGETOPTDEF s_aTeleportOptions[] =
817 {
818 { "--host", 'h', RTGETOPT_REQ_STRING }, /** @todo RTGETOPT_FLAG_MANDATORY */
819 { "--hostname", 'h', RTGETOPT_REQ_STRING }, /** @todo remove this */
820 { "--maxdowntime", 'd', RTGETOPT_REQ_UINT32 },
821 { "--port", 'p', RTGETOPT_REQ_UINT32 }, /** @todo RTGETOPT_FLAG_MANDATORY */
822 { "--password", 'P', RTGETOPT_REQ_STRING },
823 { "--timeout", 't', RTGETOPT_REQ_UINT32 }
824 };
825 RTGETOPTSTATE GetOptState;
826 RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTeleportOptions, RT_ELEMENTS(s_aTeleportOptions), 2, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
827 int ch;
828 RTGETOPTUNION Value;
829 while ( SUCCEEDED(rc)
830 && (ch = RTGetOpt(&GetOptState, &Value)))
831 {
832 switch (ch)
833 {
834 case 'h': bstrHostname = Value.psz; break;
835 case 'd': uMaxDowntime = Value.u32; break;
836 case 'p': uPort = Value.u32; break;
837 case 'P': bstrPassword = Value.psz; break;
838 case 't': cMsTimeout = Value.u32; break;
839 default:
840 errorGetOpt(USAGE_CONTROLVM, ch, &Value);
841 rc = E_FAIL;
842 break;
843 }
844 }
845 if (FAILED(rc))
846 break;
847
848 ComPtr<IProgress> progress;
849 CHECK_ERROR_BREAK(console, Teleport(bstrHostname, uPort, bstrPassword, uMaxDowntime, progress.asOutParam()));
850
851 if (cMsTimeout)
852 {
853 rc = progress->COMSETTER(Timeout)(cMsTimeout);
854 if (FAILED(rc) && rc != VBOX_E_INVALID_OBJECT_STATE)
855 CHECK_ERROR_BREAK(progress, COMSETTER(Timeout)(cMsTimeout)); /* lazyness */
856 }
857
858 rc = showProgress(progress);
859 if (FAILED(rc))
860 {
861 com::ProgressErrorInfo info(progress);
862 if (info.isBasicAvailable())
863 RTPrintf("Error: teleportation failed. Error message: %lS\n", info.getText().raw());
864 else
865 RTPrintf("Error: teleportation failed. No error message available!\n");
866 }
867 }
868 else
869 {
870 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
871 rc = E_FAIL;
872 }
873 } while (0);
874
875 a->session->Close();
876
877 return SUCCEEDED(rc) ? 0 : 1;
878}
879
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