VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp@ 31016

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

Main: unbreak frontends broken by r63924

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.1 KB
Line 
1/* $Id: VBoxManageStorageController.cpp 31016 2010-07-22 16:39:23Z vboxsync $ */
2/** @file
3 * VBoxManage - The storage controller related commands.
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#ifndef VBOX_ONLY_DOCS
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include <VBox/com/com.h>
24#include <VBox/com/array.h>
25#include <VBox/com/ErrorInfo.h>
26#include <VBox/com/errorprint.h>
27#include <VBox/com/VirtualBox.h>
28
29#include <iprt/path.h>
30#include <iprt/param.h>
31#include <iprt/string.h>
32#include <iprt/ctype.h>
33#include <iprt/stream.h>
34#include <iprt/getopt.h>
35#include <VBox/log.h>
36
37#include "VBoxManage.h"
38using namespace com;
39
40
41// funcs
42///////////////////////////////////////////////////////////////////////////////
43
44
45static const RTGETOPTDEF g_aStorageAttachOptions[] =
46{
47 { "--storagectl", 's', RTGETOPT_REQ_STRING },
48 { "--port", 'p', RTGETOPT_REQ_UINT32 },
49 { "--device", 'd', RTGETOPT_REQ_UINT32 },
50 { "--medium", 'm', RTGETOPT_REQ_STRING },
51 { "--type", 't', RTGETOPT_REQ_STRING },
52 { "--passthrough", 'h', RTGETOPT_REQ_STRING },
53 { "--forceunmount", 'f', RTGETOPT_REQ_NOTHING },
54};
55
56int handleStorageAttach(HandlerArg *a)
57{
58 int c = VERR_INTERNAL_ERROR; /* initialized to shut up gcc */
59 HRESULT rc = S_OK;
60 ULONG port = ~0U;
61 ULONG device = ~0U;
62 bool fForceUnmount = false;
63 const char *pszCtl = NULL;
64 const char *pszType = NULL;
65 const char *pszMedium = NULL;
66 const char *pszPassThrough = NULL;
67 Bstr machineuuid (a->argv[0]);
68 RTGETOPTUNION ValueUnion;
69 RTGETOPTSTATE GetState;
70 ComPtr<IMachine> machine;
71 ComPtr<IStorageController> storageCtl;
72 ComPtr<ISystemProperties> systemProperties;
73
74 if (a->argc < 9)
75 return errorSyntax(USAGE_STORAGEATTACH, "Too few parameters");
76 else if (a->argc > 13)
77 return errorSyntax(USAGE_STORAGEATTACH, "Too many parameters");
78
79 RTGetOptInit(&GetState, a->argc, a->argv, g_aStorageAttachOptions,
80 RT_ELEMENTS(g_aStorageAttachOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
81
82 while ( SUCCEEDED(rc)
83 && (c = RTGetOpt(&GetState, &ValueUnion)))
84 {
85 switch (c)
86 {
87 case 's': // storage controller name
88 {
89 if (ValueUnion.psz)
90 pszCtl = ValueUnion.psz;
91 else
92 rc = E_FAIL;
93 break;
94 }
95
96 case 'p': // port
97 {
98 port = ValueUnion.u32;
99 break;
100 }
101
102 case 'd': // device
103 {
104 device = ValueUnion.u32;
105 break;
106 }
107
108 case 'm': // medium <none|emptydrive|uuid|filename|host:<drive>>
109 {
110 if (ValueUnion.psz)
111 pszMedium = ValueUnion.psz;
112 else
113 rc = E_FAIL;
114 break;
115 }
116
117 case 't': // type <dvddrive|hdd|fdd>
118 {
119 if (ValueUnion.psz)
120 pszType = ValueUnion.psz;
121 else
122 rc = E_FAIL;
123 break;
124 }
125
126 case 'h': // passthrough <on|off>
127 {
128 if (ValueUnion.psz)
129 pszPassThrough = ValueUnion.psz;
130 else
131 rc = E_FAIL;
132 break;
133 }
134
135 case 'f': // force unmount medium during runtime
136 {
137 fForceUnmount = true;
138 break;
139 }
140
141 default:
142 {
143 errorGetOpt(USAGE_STORAGEATTACH, c, &ValueUnion);
144 rc = E_FAIL;
145 break;
146 }
147 }
148 }
149
150 if (FAILED(rc))
151 return 1;
152
153 if (!pszCtl)
154 return errorSyntax(USAGE_STORAGEATTACH, "Storage controller name not specified");
155 if (port == ~0U)
156 return errorSyntax(USAGE_STORAGEATTACH, "Port not specified");
157 if (device == ~0U)
158 return errorSyntax(USAGE_STORAGEATTACH, "Device not specified");
159
160 /* get the virtualbox system properties */
161 CHECK_ERROR_RET(a->virtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), 1);
162
163 /* try to find the given machine */
164 if (!Guid(machineuuid).isEmpty())
165 {
166 CHECK_ERROR_RET(a->virtualBox, GetMachine(machineuuid, machine.asOutParam()), 1);
167 }
168 else
169 {
170 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()), 1);
171 machine->COMGETTER(Id)(machineuuid.asOutParam());
172 }
173
174 /* open a session for the VM (new or shared) */
175 SessionType_T type;
176 rc = machine->LockForSession(a->session, true /* fPermitShared */, &type);
177 bool fRunTime = (type == SessionType_Shared);
178 if (fRunTime && !RTStrICmp(pszType, "hdd"))
179 {
180 errorArgument("Hard disk drives cannot be changed while the VM is running\n");
181 goto leave;
182 }
183
184 if (fRunTime && !RTStrICmp(pszMedium, "none"))
185 {
186 errorArgument("Drives cannot be removed while the VM is running\n");
187 goto leave;
188 }
189
190 if (fRunTime && pszPassThrough)
191 {
192 errorArgument("Drive passthrough state can't be changed while the VM is running\n");
193 goto leave;
194 }
195
196 /* get the mutable session machine */
197 a->session->COMGETTER(Machine)(machine.asOutParam());
198
199 /* check if the storage controller is present */
200 rc = machine->GetStorageControllerByName(Bstr(pszCtl), storageCtl.asOutParam());
201 if (FAILED(rc))
202 {
203 errorSyntax(USAGE_STORAGEATTACH, "Couldn't find the controller with the name: '%s'\n", pszCtl);
204 goto leave;
205 }
206
207 /* for sata controller check if the port count is big enough
208 * to accomodate the current port which is being assigned
209 * else just increase the port count
210 */
211 {
212 ULONG ulPortCount = 0;
213 ULONG ulMaxPortCount = 0;
214
215 CHECK_ERROR(storageCtl, COMGETTER(MaxPortCount)(&ulMaxPortCount));
216 CHECK_ERROR(storageCtl, COMGETTER(PortCount)(&ulPortCount));
217
218 if ( (ulPortCount != ulMaxPortCount)
219 && (port >= ulPortCount)
220 && (port < ulMaxPortCount))
221 CHECK_ERROR(storageCtl, COMSETTER(PortCount)(port + 1));
222 }
223
224 if (!RTStrICmp(pszMedium, "none"))
225 {
226 CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl), port, device));
227 }
228 else if (!RTStrICmp(pszMedium, "emptydrive"))
229 {
230 if (fRunTime)
231 {
232 ComPtr<IMediumAttachment> mediumAttachment;
233 DeviceType_T deviceType = DeviceType_Null;
234 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachment.asOutParam());
235 if (SUCCEEDED(rc))
236 {
237 mediumAttachment->COMGETTER(Type)(&deviceType);
238
239 if ( (deviceType == DeviceType_DVD)
240 || (deviceType == DeviceType_Floppy))
241 {
242 /* just unmount the floppy/dvd */
243 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl), port, device, Bstr(""), fForceUnmount));
244 }
245 }
246
247 if ( FAILED(rc)
248 || !( deviceType == DeviceType_DVD
249 || deviceType == DeviceType_Floppy))
250 {
251 errorArgument("No DVD/Floppy Drive attached to the controller '%s'"
252 "at the port: %u, device: %u", pszCtl, port, device);
253 goto leave;
254 }
255
256 }
257 else
258 {
259 StorageBus_T storageBus = StorageBus_Null;
260 DeviceType_T deviceType = DeviceType_Null;
261 com::SafeArray <DeviceType_T> saDeviceTypes;
262 ULONG driveCheck = 0;
263
264 /* check if the device type is supported by the controller */
265 CHECK_ERROR(storageCtl, COMGETTER(Bus)(&storageBus));
266 CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
267 for (size_t i = 0; i < saDeviceTypes.size(); ++ i)
268 {
269 if ( (saDeviceTypes[i] == DeviceType_DVD)
270 || (saDeviceTypes[i] == DeviceType_Floppy))
271 driveCheck++;
272 }
273
274 if (!driveCheck)
275 {
276 errorArgument("The Attachment is not supported by the Storage Controller: '%s'", pszCtl);
277 goto leave;
278 }
279
280 if (storageBus == StorageBus_Floppy)
281 deviceType = DeviceType_Floppy;
282 else
283 deviceType = DeviceType_DVD;
284
285 /* attach a empty floppy/dvd drive after removing previous attachment */
286 machine->DetachDevice(Bstr(pszCtl), port, device);
287 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, deviceType, Bstr("")));
288 }
289 }
290 else
291 {
292 {
293 /*
294 * try to determine the type of the drive from the
295 * storage controller chipset, the attachment and
296 * the medium being attached
297 */
298 StorageControllerType_T ctlType = StorageControllerType_Null;
299 CHECK_ERROR(storageCtl, COMGETTER(ControllerType)(&ctlType));
300 if (ctlType == StorageControllerType_I82078)
301 {
302 /*
303 * floppy controller found so lets assume the medium
304 * given by the user is also a floppy image or floppy
305 * host drive
306 */
307 pszType = "fdd";
308 }
309 else
310 {
311 /*
312 * for SATA/SCSI/IDE it is hard to tell if it is a harddisk or
313 * a dvd being attached so lets check if the medium attachment
314 * and the medium, both are of same type. if yes then we are
315 * sure of its type and don't need the user to enter it manually
316 * else ask the user for the type.
317 */
318 ComPtr<IMediumAttachment> mediumAttachement;
319 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachement.asOutParam());
320 if (SUCCEEDED(rc))
321 {
322 DeviceType_T deviceType;
323 mediumAttachement->COMGETTER(Type)(&deviceType);
324
325 if (deviceType == DeviceType_DVD)
326 {
327 Bstr uuid(pszMedium);
328 ComPtr<IMedium> dvdMedium;
329 /* first assume it's a UUID */
330 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
331 if (FAILED(rc) || !dvdMedium)
332 {
333 /* must be a filename, check if it's in the collection */
334 a->virtualBox->FindDVDImage(Bstr(pszMedium), dvdMedium.asOutParam());
335 }
336 if (dvdMedium)
337 {
338 /*
339 * ok so the medium and attachment both are DVD's so it is
340 * safe to assume that we are dealing with a DVD here
341 */
342 pszType = "dvddrive";
343 }
344 }
345 else if (deviceType == DeviceType_HardDisk)
346 {
347 Bstr uuid(pszMedium);
348 ComPtr<IMedium> hardDisk;
349 /* first assume it's a UUID */
350 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
351 if (FAILED(rc) || !hardDisk)
352 {
353 /* must be a filename, check if it's in the collection */
354 a->virtualBox->FindHardDisk(Bstr(pszMedium), hardDisk.asOutParam());
355 }
356 if (hardDisk)
357 {
358 /*
359 * ok so the medium and attachment both are hdd's so it is
360 * safe to assume that we are dealing with a hdd here
361 */
362 pszType = "hdd";
363 }
364 }
365 }
366 }
367 /* for all other cases lets ask the user what type of drive it is */
368 }
369
370 if (!pszType)
371 {
372 errorSyntax(USAGE_STORAGEATTACH, "Argument --type not specified\n");
373 goto leave;
374 }
375
376 /* check if the device type is supported by the controller */
377 {
378 StorageBus_T storageBus = StorageBus_Null;
379 com::SafeArray <DeviceType_T> saDeviceTypes;
380
381 CHECK_ERROR(storageCtl, COMGETTER(Bus)(&storageBus));
382 CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
383 if (SUCCEEDED(rc))
384 {
385 ULONG driveCheck = 0;
386 for (size_t i = 0; i < saDeviceTypes.size(); ++ i)
387 {
388 if ( !RTStrICmp(pszType, "dvddrive")
389 && (saDeviceTypes[i] == DeviceType_DVD))
390 driveCheck++;
391
392 if ( !RTStrICmp(pszType, "hdd")
393 && (saDeviceTypes[i] == DeviceType_HardDisk))
394 driveCheck++;
395
396 if ( !RTStrICmp(pszType, "fdd")
397 && (saDeviceTypes[i] == DeviceType_Floppy))
398 driveCheck++;
399 }
400 if (!driveCheck)
401 {
402 errorArgument("The Attachment is not supported by the Storage Controller: '%s'", pszCtl);
403 goto leave;
404 }
405 }
406 else
407 goto leave;
408 }
409
410 if (!RTStrICmp(pszType, "dvddrive"))
411 {
412 Bstr uuid;
413 ComPtr<IMedium> dvdMedium;
414
415 if (!fRunTime)
416 {
417 ComPtr<IMediumAttachment> mediumAttachement;
418
419 /* check if there is a dvd drive at the given location, if not attach one */
420 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachement.asOutParam());
421 if (SUCCEEDED(rc))
422 {
423 DeviceType_T deviceType;
424 mediumAttachement->COMGETTER(Type)(&deviceType);
425
426 if (deviceType != DeviceType_DVD)
427 {
428 machine->DetachDevice(Bstr(pszCtl), port, device);
429 rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, Bstr(""));
430 }
431 }
432 else
433 {
434 rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, Bstr(""));
435 }
436 }
437
438 /* Attach/Detach the dvd medium now */
439 do
440 {
441 /* host drive? */
442 if (!RTStrNICmp(pszMedium, "host:", 5))
443 {
444 ComPtr<IHost> host;
445 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
446 rc = host->FindHostDVDDrive(Bstr(pszMedium + 5), dvdMedium.asOutParam());
447 if (!dvdMedium)
448 {
449 /* 2nd try: try with the real name, important on Linux+libhal */
450 char szPathReal[RTPATH_MAX];
451 if (RT_FAILURE(RTPathReal(pszMedium + 5, szPathReal, sizeof(szPathReal))))
452 {
453 errorArgument("Invalid host DVD drive name \"%s\"", pszMedium + 5);
454 rc = E_FAIL;
455 break;
456 }
457 rc = host->FindHostDVDDrive(Bstr(szPathReal), dvdMedium.asOutParam());
458 if (!dvdMedium)
459 {
460 errorArgument("Invalid host DVD drive name \"%s\"", pszMedium + 5);
461 rc = E_FAIL;
462 break;
463 }
464 }
465 }
466 else
467 {
468 /* first assume it's a UUID */
469 uuid = pszMedium;
470 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
471 if (FAILED(rc) || !dvdMedium)
472 {
473 /* must be a filename, check if it's in the collection */
474 rc = a->virtualBox->FindDVDImage(Bstr(pszMedium), dvdMedium.asOutParam());
475 /* not registered, do that on the fly */
476 if (!dvdMedium)
477 {
478 Bstr emptyUUID;
479 CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(pszMedium),
480 emptyUUID, dvdMedium.asOutParam()));
481 }
482 }
483 if (!dvdMedium)
484 {
485 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
486 rc = E_FAIL;
487 break;
488 }
489 }
490 } while (0);
491
492 if (dvdMedium)
493 {
494 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
495 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl), port, device, uuid, fForceUnmount));
496 }
497 }
498 else if ( !RTStrICmp(pszType, "hdd")
499 && !fRunTime)
500 {
501 ComPtr<IMediumAttachment> mediumAttachement;
502
503 /* if there is anything attached at the given location, remove it */
504 machine->DetachDevice(Bstr(pszCtl), port, device);
505
506 /* first guess is that it's a UUID */
507 Bstr uuid(pszMedium);
508 ComPtr<IMedium> hardDisk;
509 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
510
511 /* not successful? Then it must be a filename */
512 if (!hardDisk)
513 {
514 rc = a->virtualBox->FindHardDisk(Bstr(pszMedium), hardDisk.asOutParam());
515 if (FAILED(rc))
516 {
517 /* open the new hard disk object */
518 CHECK_ERROR(a->virtualBox,
519 OpenHardDisk(Bstr(pszMedium),
520 AccessMode_ReadWrite, false, Bstr(""),
521 false, Bstr(""), hardDisk.asOutParam()));
522 }
523 }
524
525 if (hardDisk)
526 {
527 hardDisk->COMGETTER(Id)(uuid.asOutParam());
528 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_HardDisk, uuid));
529 }
530 else
531 {
532 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
533 rc = E_FAIL;
534 }
535 }
536 else if (!RTStrICmp(pszType, "fdd"))
537 {
538 Bstr uuid;
539 ComPtr<IMedium> floppyMedium;
540 ComPtr<IMediumAttachment> floppyAttachment;
541 machine->GetMediumAttachment(Bstr(pszCtl), port, device, floppyAttachment.asOutParam());
542
543 if ( !fRunTime
544 && !floppyAttachment)
545 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_Floppy, Bstr("")));
546
547 /* host drive? */
548 if (!RTStrNICmp(pszMedium, "host:", 5))
549 {
550 ComPtr<IHost> host;
551
552 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
553 rc = host->FindHostFloppyDrive(Bstr(pszMedium + 5), floppyMedium.asOutParam());
554 if (!floppyMedium)
555 {
556 errorArgument("Invalid host floppy drive name \"%s\"", pszMedium + 5);
557 rc = E_FAIL;
558 }
559 }
560 else
561 {
562 /* first assume it's a UUID */
563 uuid = pszMedium;
564 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
565 if (FAILED(rc) || !floppyMedium)
566 {
567 /* must be a filename, check if it's in the collection */
568 rc = a->virtualBox->FindFloppyImage(Bstr(pszMedium), floppyMedium.asOutParam());
569 /* not registered, do that on the fly */
570 if (!floppyMedium)
571 {
572 Bstr emptyUUID;
573 CHECK_ERROR(a->virtualBox,
574 OpenFloppyImage(Bstr(pszMedium),
575 emptyUUID,
576 floppyMedium.asOutParam()));
577 }
578 }
579
580 if (!floppyMedium)
581 {
582 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
583 rc = E_FAIL;
584 }
585 }
586
587 if (floppyMedium)
588 {
589 floppyMedium->COMGETTER(Id)(uuid.asOutParam());
590 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl), port, device, uuid, fForceUnmount));
591 }
592 }
593 else
594 {
595 errorArgument("Invalid --type argument '%s'", pszType);
596 rc = E_FAIL;
597 }
598 }
599
600 if ( pszPassThrough
601 && (SUCCEEDED(rc)))
602 {
603 ComPtr<IMediumAttachment> mattach;
604
605 CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl), port, device, mattach.asOutParam()));
606
607 if (SUCCEEDED(rc))
608 {
609 if (!RTStrICmp(pszPassThrough, "on"))
610 {
611 CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl), port, device, TRUE));
612 }
613 else if (!RTStrICmp(pszPassThrough, "off"))
614 {
615 CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl), port, device, FALSE));
616 }
617 else
618 {
619 errorArgument("Invalid --passthrough argument '%s'", pszPassThrough);
620 rc = E_FAIL;
621 }
622 }
623 else
624 {
625 errorArgument("Couldn't find the controller attachment for the controller '%s'\n", pszCtl);
626 rc = E_FAIL;
627 }
628 }
629
630 /* commit changes */
631 if (SUCCEEDED(rc))
632 CHECK_ERROR(machine, SaveSettings());
633
634leave:
635 /* it's important to always close sessions */
636 a->session->Close();
637
638 return SUCCEEDED(rc) ? 0 : 1;
639}
640
641
642static const RTGETOPTDEF g_aStorageControllerOptions[] =
643{
644 { "--name", 'n', RTGETOPT_REQ_STRING },
645 { "--add", 'a', RTGETOPT_REQ_STRING },
646 { "--controller", 'c', RTGETOPT_REQ_STRING },
647 { "--sataideemulation", 'e', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX },
648 { "--sataportcount", 'p', RTGETOPT_REQ_UINT32 },
649 { "--remove", 'r', RTGETOPT_REQ_NOTHING },
650 { "--hostiocache", 'i', RTGETOPT_REQ_STRING },
651};
652
653int handleStorageController(HandlerArg *a)
654{
655 int c;
656 HRESULT rc = S_OK;
657 const char *pszCtl = NULL;
658 const char *pszBusType = NULL;
659 const char *pszCtlType = NULL;
660 const char *pszHostIOCache = NULL;
661 ULONG satabootdev = ~0U;
662 ULONG sataidedev = ~0U;
663 ULONG sataportcount = ~0U;
664 bool fRemoveCtl = false;
665 Bstr machineuuid (a->argv[0]);
666 ComPtr<IMachine> machine;
667 RTGETOPTUNION ValueUnion;
668 RTGETOPTSTATE GetState;
669
670 if (a->argc < 4)
671 return errorSyntax(USAGE_STORAGECONTROLLER, "Too few parameters");
672
673 RTGetOptInit (&GetState, a->argc, a->argv, g_aStorageControllerOptions,
674 RT_ELEMENTS(g_aStorageControllerOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
675
676 while ( SUCCEEDED(rc)
677 && (c = RTGetOpt(&GetState, &ValueUnion)))
678 {
679 switch (c)
680 {
681 case 'n': // controller name
682 {
683 if (ValueUnion.psz)
684 pszCtl = ValueUnion.psz;
685 else
686 rc = E_FAIL;
687 break;
688 }
689
690 case 'a': // controller bus type <ide/sata/scsi/floppy>
691 {
692 if (ValueUnion.psz)
693 pszBusType = ValueUnion.psz;
694 else
695 rc = E_FAIL;
696 break;
697 }
698
699 case 'c': // controller <lsilogic/buslogic/intelahci/piix3/piix4/ich6/i82078>
700 {
701 if (ValueUnion.psz)
702 pszCtlType = ValueUnion.psz;
703 else
704 rc = E_FAIL;
705 break;
706 }
707
708 case 'e': // sataideemulation
709 {
710 satabootdev = GetState.uIndex;
711 sataidedev = ValueUnion.u32;
712 break;
713 }
714
715 case 'p': // sataportcount
716 {
717 sataportcount = ValueUnion.u32;
718 break;
719 }
720
721 case 'r': // remove controller
722 {
723 fRemoveCtl = true;
724 break;
725 }
726
727 case 'i':
728 {
729 pszHostIOCache = ValueUnion.psz;
730 break;
731 }
732
733 default:
734 {
735 errorGetOpt(USAGE_STORAGECONTROLLER, c, &ValueUnion);
736 rc = E_FAIL;
737 break;
738 }
739 }
740 }
741
742 if (FAILED(rc))
743 return 1;
744
745 /* try to find the given machine */
746 if (!Guid(machineuuid).isEmpty())
747 {
748 CHECK_ERROR_RET(a->virtualBox, GetMachine (machineuuid, machine.asOutParam()), 1);
749 }
750 else
751 {
752 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()), 1);
753 machine->COMGETTER(Id)(machineuuid.asOutParam());
754 }
755
756 /* open a session for the VM */
757 SessionType_T st;
758 CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1);
759
760 /* get the mutable session machine */
761 a->session->COMGETTER(Machine)(machine.asOutParam());
762
763 if (!pszCtl)
764 {
765 /* it's important to always close sessions */
766 a->session->Close();
767 errorSyntax(USAGE_STORAGECONTROLLER, "Storage controller name not specified\n");
768 return 1;
769 }
770
771 if (fRemoveCtl)
772 {
773 com::SafeIfaceArray<IMediumAttachment> mediumAttachments;
774
775 CHECK_ERROR(machine,
776 GetMediumAttachmentsOfController(Bstr(pszCtl),
777 ComSafeArrayAsOutParam(mediumAttachments)));
778 for (size_t i = 0; i < mediumAttachments.size(); ++ i)
779 {
780 ComPtr<IMediumAttachment> mediumAttach = mediumAttachments[i];
781 LONG port = 0;
782 LONG device = 0;
783
784 CHECK_ERROR(mediumAttach, COMGETTER(Port)(&port));
785 CHECK_ERROR(mediumAttach, COMGETTER(Device)(&device));
786 CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl), port, device));
787 }
788
789 if (SUCCEEDED(rc))
790 CHECK_ERROR(machine, RemoveStorageController(Bstr(pszCtl)));
791 else
792 errorArgument("Can't detach the devices connected to '%s' Controller\n"
793 "and thus its removal failed.", pszCtl);
794 }
795 else
796 {
797 if (pszBusType)
798 {
799 ComPtr<IStorageController> ctl;
800
801 if (!RTStrICmp(pszBusType, "ide"))
802 {
803 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_IDE, ctl.asOutParam()));
804 }
805 else if (!RTStrICmp(pszBusType, "sata"))
806 {
807 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_SATA, ctl.asOutParam()));
808 }
809 else if (!RTStrICmp(pszBusType, "scsi"))
810 {
811 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_SCSI, ctl.asOutParam()));
812 }
813 else if (!RTStrICmp(pszBusType, "floppy"))
814 {
815 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_Floppy, ctl.asOutParam()));
816 }
817 else if (!RTStrICmp(pszBusType, "sas"))
818 {
819 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_SAS, ctl.asOutParam()));
820 }
821 else
822 {
823 errorArgument("Invalid --add argument '%s'", pszBusType);
824 rc = E_FAIL;
825 }
826 }
827
828 if ( pszCtlType
829 && SUCCEEDED(rc))
830 {
831 ComPtr<IStorageController> ctl;
832
833 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
834
835 if (SUCCEEDED(rc))
836 {
837 if (!RTStrICmp(pszCtlType, "lsilogic"))
838 {
839 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogic));
840 }
841 else if (!RTStrICmp(pszCtlType, "buslogic"))
842 {
843 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic));
844 }
845 else if (!RTStrICmp(pszCtlType, "intelahci"))
846 {
847 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_IntelAhci));
848 }
849 else if (!RTStrICmp(pszCtlType, "piix3"))
850 {
851 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX3));
852 }
853 else if (!RTStrICmp(pszCtlType, "piix4"))
854 {
855 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX4));
856 }
857 else if (!RTStrICmp(pszCtlType, "ich6"))
858 {
859 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_ICH6));
860 }
861 else if (!RTStrICmp(pszCtlType, "i82078"))
862 {
863 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_I82078));
864 }
865 else if (!RTStrICmp(pszCtlType, "lsilogicsas"))
866 {
867 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogicSas));
868 }
869 else
870 {
871 errorArgument("Invalid --type argument '%s'", pszCtlType);
872 rc = E_FAIL;
873 }
874 }
875 else
876 {
877 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
878 rc = E_FAIL;
879 }
880 }
881
882 if ( (sataportcount != ~0U)
883 && SUCCEEDED(rc))
884 {
885 ComPtr<IStorageController> ctl;
886
887 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
888
889 if (SUCCEEDED(rc))
890 {
891 CHECK_ERROR(ctl, COMSETTER(PortCount)(sataportcount));
892 }
893 else
894 {
895 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
896 rc = E_FAIL;
897 }
898 }
899
900 if ( (sataidedev != ~0U)
901 && (satabootdev != ~0U)
902 && SUCCEEDED(rc))
903 {
904 ComPtr<IStorageController> ctl;
905
906 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
907
908 if (SUCCEEDED(rc))
909 {
910 CHECK_ERROR(ctl, SetIDEEmulationPort(satabootdev, sataidedev));
911 }
912 else
913 {
914 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
915 rc = E_FAIL;
916 }
917 }
918
919 if ( pszHostIOCache
920 && SUCCEEDED(rc))
921 {
922 ComPtr<IStorageController> ctl;
923
924 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
925
926 if (SUCCEEDED(rc))
927 {
928 if (!RTStrICmp(pszHostIOCache, "on"))
929 {
930 CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(TRUE));
931 }
932 else if (!RTStrICmp(pszHostIOCache, "off"))
933 {
934 CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(FALSE));
935 }
936 else
937 {
938 errorArgument("Invalid --hostiocache argument '%s'", pszHostIOCache);
939 rc = E_FAIL;
940 }
941 }
942 else
943 {
944 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
945 rc = E_FAIL;
946 }
947 }
948 }
949
950 /* commit changes */
951 if (SUCCEEDED(rc))
952 CHECK_ERROR(machine, SaveSettings());
953
954 /* it's important to always close sessions */
955 a->session->Close();
956
957 return SUCCEEDED(rc) ? 0 : 1;
958}
959
960#endif /* !VBOX_ONLY_DOCS */
961
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