VBoxManageStorageController.cpp revision aeb9498c4d9854ed42b271541d34c7bad97b4c77
/* $Id$ */
/** @file
* VBoxManage - The storage controller related commands.
*/
/*
* Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifndef VBOX_ONLY_DOCS
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "VBoxManage.h"
using namespace com;
// funcs
///////////////////////////////////////////////////////////////////////////////
static const RTGETOPTDEF g_aStorageAttachOptions[] =
{
// iSCSI options
};
int handleStorageAttach(HandlerArg *a)
{
int c = VERR_INTERNAL_ERROR; /* initialized to shut up gcc */
bool fForceUnmount = false;
const char *pszPassThrough = NULL;
const char *pszBandwidthGroup = NULL;
// iSCSI options
bool fIntNet = false;
{
switch (c)
{
case 's': // storage controller name
{
if (ValueUnion.psz)
else
break;
}
case 'p': // port
{
break;
}
case 'd': // device
{
break;
}
case 'm': // medium <none|emptydrive|uuid|filename|host:<drive>|iSCSI>
{
if (ValueUnion.psz)
else
break;
}
case 't': // type <dvddrive|hdd|fdd>
{
if (ValueUnion.psz)
{
else
}
else
break;
}
case 'h': // passthrough <on|off>
{
if (ValueUnion.psz)
else
break;
}
case 'b': // bandwidthgroup <name>
{
if (ValueUnion.psz)
else
break;
}
case 'f': // force unmount medium during runtime
{
fForceUnmount = true;
break;
}
case 'C':
if (ValueUnion.psz)
else
break;
case 'S': // --server
break;
case 'T': // --target
break;
case 'P': // --port
break;
case 'L': // --lun
break;
case 'E': // --encodedlun
break;
case 'U': // --username
break;
case 'W': // --password
break;
case 'M': // --type
{
if (RT_FAILURE(vrc))
break;
}
case 'I': // --intnet
fIntNet = true;
break;
default:
{
break;
}
}
}
return 1;
if (!pszCtl)
if (port == ~0U)
if (device == ~0U)
/* get the virtualbox system properties */
// find the machine, lock it, get the mutable session machine
try
{
if (fRunTime)
{
if (devTypeRequested == DeviceType_HardDisk)
throw Utf8Str("Hard disk drives cannot be changed while the VM is running\n");
throw Utf8Str("Drives cannot be removed while the VM is running\n");
else if (pszPassThrough)
throw Utf8Str("Drive passthrough state cannot be changed while the VM is running\n");
else if (pszBandwidthGroup)
throw Utf8Str("Bandwidth group cannot be changed while the VM is running\n");
}
/* check if the storage controller is present */
storageCtl.asOutParam());
/* for sata controller check if the port count is big enough
* to accommodate the current port which is being assigned
* else just increase the port count
*/
{
ULONG ulPortCount = 0;
ULONG ulMaxPortCount = 0;
if ( (ulPortCount != ulMaxPortCount)
&& (port >= ulPortCount)
&& (port < ulMaxPortCount))
}
{
}
{
if (fRunTime)
{
{
if ( (deviceType == DeviceType_DVD)
|| (deviceType == DeviceType_Floppy))
{
port,
NULL,
}
}
|| !( deviceType == DeviceType_DVD
|| deviceType == DeviceType_Floppy)
)
throw Utf8StrFmt("No DVD/Floppy Drive attached to the controller '%s'"
}
else
{
ULONG driveCheck = 0;
/* check if the device type is supported by the controller */
CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
{
if ( (saDeviceTypes[i] == DeviceType_DVD)
|| (saDeviceTypes[i] == DeviceType_Floppy))
driveCheck++;
}
if (!driveCheck)
if (storageBus == StorageBus_Floppy)
else
deviceType, NULL));
}
} // end if (!RTStrICmp(pszMedium, "emptydrive"))
else
{
// not "none", not "emptydrive": then it must be a UUID or filename or hostdrive or iSCSI;
// for all these we first need to know the type of drive we're attaching to
{
/*
* try to determine the type of the drive from the
* storage controller chipset, the attachment and
* the medium being attached
*/
else
{
/*
* a dvd being attached so lets check if the medium attachment
* and the medium, both are of same type. if yes then we are
* sure of its type and don't need the user to enter it manually
* else ask the user for the type.
*/
{
if (pExistingMedium)
{
if ( (deviceType == DeviceType_DVD)
|| (deviceType == DeviceType_HardDisk)
)
}
}
}
/* for all other cases lets ask the user what type of drive it is */
}
throw Utf8Str("Argument --type must be specified\n");
/* check if the device type is supported by the controller */
{
CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
{
ULONG driveCheck = 0;
if (saDeviceTypes[i] == devTypeRequested)
driveCheck++;
if (!driveCheck)
}
else
goto leave;
}
// find the medium given
/* host drive? */
{
if (devTypeRequested == DeviceType_DVD)
{
if (!pMedium2Mount)
{
/* 2nd try: try with the real name, important on Linux+libhal */
char szPathReal[RTPATH_MAX];
if (!pMedium2Mount)
}
}
else
{
// floppy
if (!pMedium2Mount)
}
}
{
/* check for required options */
throw Utf8StrFmt("Parameters --server and --target are required for iSCSI media");
/** @todo move the location stuff to Main, which can use pfnComposeName
* from the disk backends to construct the location properly. Also do
* not use slashes to separate the parts, as otherwise only the last
* element containing information will be shown. */
|| (bstrLun == "0")
|| (bstrLun == "enc0")
)
else
pMedium2Mount.asOutParam()));
// set the other iSCSI parameters as properties
{
}
if (!bstrUsername.isEmpty())
{
}
if (!bstrPassword.isEmpty())
{
}
/// @todo add --initiator option - until that happens rely on the
// defaults of the iSCSI initiator code. Setting it to a constant
// value does more harm than good, as the initiator name is supposed
// to identify a particular initiator uniquely.
// Bstr("InitiatorName").detachTo(names.appendedRaw());
// Bstr("iqn.2008-04.com.sun.virtualbox.initiator").detachTo(values.appendedRaw());
/// @todo add --targetName and --targetPassword options
if (fIntNet)
{
}
}
else
{
if (bstrMedium.isEmpty())
throw Utf8Str("Missing --medium argument");
{
/* not registered, do that on the fly */
pMedium2Mount.asOutParam()));
}
if (!pMedium2Mount)
}
switch (devTypeRequested)
{
case DeviceType_DVD:
case DeviceType_Floppy:
{
if (!fRunTime)
{
port,
{
if (deviceType != devTypeRequested)
{
port,
devTypeRequested, // DeviceType_DVD or DeviceType_Floppy
NULL);
}
}
else
{
port,
devTypeRequested, // DeviceType_DVD or DeviceType_Floppy
NULL);
}
}
if (pMedium2Mount)
{
port,
}
} // end DeviceType_DVD or DeviceType_Floppy:
break;
case DeviceType_HardDisk:
{
if (fRunTime)
throw Utf8Str("Hard disk attachments cannot be changed while the VM is running");
// if there is anything attached at the given location, remove it
port,
}
break;
}
// set medium type, if so desired
{
}
if (!bstrComment.isEmpty())
{
}
}
if ( pszPassThrough
{
{
{
}
{
}
else
}
else
}
if ( pszBandwidthGroup
&& !fRunTime
{
{
/* Just remove the bandwidth gorup. */
}
else
{
{
{
}
}
}
}
/* commit changes */
}
{
}
// machine must always be unlocked, even on errors
a->session->UnlockMachine();
}
static const RTGETOPTDEF g_aStorageControllerOptions[] =
{
};
int handleStorageController(HandlerArg *a)
{
int c;
const char *pszBusType = NULL;
const char *pszCtlType = NULL;
const char *pszHostIOCache = NULL;
const char *pszBootable = NULL;
ULONG satabootdev = ~0U;
ULONG sataidedev = ~0U;
ULONG sataportcount = ~0U;
bool fRemoveCtl = false;
if (a->argc < 4)
{
switch (c)
{
case 'n': // controller name
{
if (ValueUnion.psz)
else
break;
}
{
if (ValueUnion.psz)
else
break;
}
{
if (ValueUnion.psz)
else
break;
}
case 'e': // sataideemulation
{
break;
}
case 'p': // sataportcount
{
break;
}
case 'r': // remove controller
{
fRemoveCtl = true;
break;
}
case 'i':
{
break;
}
case 'b':
{
break;
}
default:
{
break;
}
}
}
return 1;
/* try to find the given machine */
/* open a session for the VM */
/* get the mutable session machine */
if (!pszCtl)
{
/* it's important to always close sessions */
a->session->UnlockMachine();
return 1;
}
if (fRemoveCtl)
{
{
}
else
errorArgument("Can't detach the devices connected to '%s' Controller\n"
"and thus its removal failed.", pszCtl);
}
else
{
if (pszBusType)
{
{
ctl.asOutParam()));
}
{
ctl.asOutParam()));
}
{
ctl.asOutParam()));
}
{
ctl.asOutParam()));
}
{
ctl.asOutParam()));
}
else
{
}
}
if ( pszCtlType
{
ctl.asOutParam()));
{
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
else
{
}
}
else
{
}
}
if ( (sataportcount != ~0U)
{
ctl.asOutParam()));
{
}
else
{
}
}
if ( (sataidedev != ~0U)
&& (satabootdev != ~0U)
{
ctl.asOutParam()));
{
}
else
{
}
}
if ( pszHostIOCache
{
ctl.asOutParam()));
{
{
}
{
}
else
{
}
}
else
{
}
}
if ( pszBootable
{
{
{
}
{
}
else
{
}
}
else
{
}
}
}
/* commit changes */
/* it's important to always close sessions */
a->session->UnlockMachine();
}
#endif /* !VBOX_ONLY_DOCS */