VirtualBox

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

Last change on this file since 32246 was 31615, checked in by vboxsync, 14 years ago

Main: Implemenation of per-machine media registries; VirtualBox::openMedium() no longer adds media to the global registry, instead a media are stored in a machine XML registry after Machine::AttachDevice() has been called; Machine::AttachDevice() now takes an IMedium object instead of a UUID; also make Machine::Unregister() work again for inaccessible machines

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