[23802] | 1 | /* $Id: VBoxManageStorageController.cpp 101035 2023-09-07 08:59:15Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * VBoxManage - The storage controller related commands.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[23802] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[23802] | 26 | */
|
---|
| 27 |
|
---|
[94236] | 28 |
|
---|
[57358] | 29 | /*********************************************************************************************************************************
|
---|
| 30 | * Header Files *
|
---|
| 31 | *********************************************************************************************************************************/
|
---|
[23802] | 32 | #include <VBox/com/com.h>
|
---|
| 33 | #include <VBox/com/array.h>
|
---|
| 34 | #include <VBox/com/ErrorInfo.h>
|
---|
| 35 | #include <VBox/com/errorprint.h>
|
---|
| 36 | #include <VBox/com/VirtualBox.h>
|
---|
| 37 |
|
---|
| 38 | #include <iprt/path.h>
|
---|
| 39 | #include <iprt/param.h>
|
---|
| 40 | #include <iprt/string.h>
|
---|
| 41 | #include <iprt/ctype.h>
|
---|
| 42 | #include <iprt/stream.h>
|
---|
| 43 | #include <iprt/getopt.h>
|
---|
| 44 | #include <VBox/log.h>
|
---|
| 45 |
|
---|
| 46 | #include "VBoxManage.h"
|
---|
| 47 | using namespace com;
|
---|
| 48 |
|
---|
[92372] | 49 | DECLARE_TRANSLATION_CONTEXT(Storage);
|
---|
[23802] | 50 |
|
---|
| 51 | // funcs
|
---|
| 52 | ///////////////////////////////////////////////////////////////////////////////
|
---|
| 53 |
|
---|
| 54 |
|
---|
[23902] | 55 | static const RTGETOPTDEF g_aStorageAttachOptions[] =
|
---|
[23802] | 56 | {
|
---|
[34634] | 57 | { "--storagectl", 's', RTGETOPT_REQ_STRING },
|
---|
| 58 | { "--port", 'p', RTGETOPT_REQ_UINT32 },
|
---|
| 59 | { "--device", 'd', RTGETOPT_REQ_UINT32 },
|
---|
| 60 | { "--type", 't', RTGETOPT_REQ_STRING },
|
---|
| 61 | { "--medium", 'm', RTGETOPT_REQ_STRING },
|
---|
| 62 | { "--mtype", 'M', RTGETOPT_REQ_STRING },
|
---|
| 63 | { "--passthrough", 'h', RTGETOPT_REQ_STRING },
|
---|
[37709] | 64 | { "--tempeject", 'e', RTGETOPT_REQ_STRING },
|
---|
[37824] | 65 | { "--nonrotational", 'n', RTGETOPT_REQ_STRING },
|
---|
[38874] | 66 | { "--discard", 'u', RTGETOPT_REQ_STRING },
|
---|
[49190] | 67 | { "--hotpluggable", 'o', RTGETOPT_REQ_STRING },
|
---|
[34634] | 68 | { "--bandwidthgroup", 'b', RTGETOPT_REQ_STRING },
|
---|
| 69 | { "--forceunmount", 'f', RTGETOPT_REQ_NOTHING },
|
---|
| 70 | { "--comment", 'C', RTGETOPT_REQ_STRING },
|
---|
[37525] | 71 | { "--setuuid", 'q', RTGETOPT_REQ_STRING },
|
---|
| 72 | { "--setparentuuid", 'Q', RTGETOPT_REQ_STRING },
|
---|
[34634] | 73 | // iSCSI options
|
---|
| 74 | { "--server", 'S', RTGETOPT_REQ_STRING },
|
---|
| 75 | { "--target", 'T', RTGETOPT_REQ_STRING },
|
---|
[37929] | 76 | { "--tport", 'P', RTGETOPT_REQ_STRING },
|
---|
[34634] | 77 | { "--lun", 'L', RTGETOPT_REQ_STRING },
|
---|
| 78 | { "--encodedlun", 'E', RTGETOPT_REQ_STRING },
|
---|
| 79 | { "--username", 'U', RTGETOPT_REQ_STRING },
|
---|
| 80 | { "--password", 'W', RTGETOPT_REQ_STRING },
|
---|
[69681] | 81 | { "--passwordfile", 'w', RTGETOPT_REQ_STRING },
|
---|
[42395] | 82 | { "--initiator", 'N', RTGETOPT_REQ_STRING },
|
---|
[34634] | 83 | { "--intnet", 'I', RTGETOPT_REQ_NOTHING },
|
---|
[23802] | 84 | };
|
---|
| 85 |
|
---|
[56118] | 86 | RTEXITCODE handleStorageAttach(HandlerArg *a)
|
---|
[23802] | 87 | {
|
---|
[24678] | 88 | int c = VERR_INTERNAL_ERROR; /* initialized to shut up gcc */
|
---|
[95140] | 89 | HRESULT hrc = S_OK;
|
---|
[23902] | 90 | ULONG port = ~0U;
|
---|
[37929] | 91 | ULONG device = ~0U;
|
---|
[24504] | 92 | bool fForceUnmount = false;
|
---|
[35136] | 93 | bool fSetMediumType = false;
|
---|
[37525] | 94 | bool fSetNewUuid = false;
|
---|
| 95 | bool fSetNewParentUuid = false;
|
---|
[54438] | 96 | MediumType_T enmMediumType = MediumType_Normal;
|
---|
[34634] | 97 | Bstr bstrComment;
|
---|
[23802] | 98 | const char *pszCtl = NULL;
|
---|
[34634] | 99 | DeviceType_T devTypeRequested = DeviceType_Null;
|
---|
[23902] | 100 | const char *pszMedium = NULL;
|
---|
| 101 | const char *pszPassThrough = NULL;
|
---|
[37709] | 102 | const char *pszTempEject = NULL;
|
---|
[37824] | 103 | const char *pszNonRotational = NULL;
|
---|
[38874] | 104 | const char *pszDiscard = NULL;
|
---|
[49190] | 105 | const char *pszHotPluggable = NULL;
|
---|
[34587] | 106 | const char *pszBandwidthGroup = NULL;
|
---|
[37525] | 107 | Bstr bstrNewUuid;
|
---|
| 108 | Bstr bstrNewParentUuid;
|
---|
[34634] | 109 | // iSCSI options
|
---|
| 110 | Bstr bstrServer;
|
---|
| 111 | Bstr bstrTarget;
|
---|
| 112 | Bstr bstrPort;
|
---|
| 113 | Bstr bstrLun;
|
---|
| 114 | Bstr bstrUsername;
|
---|
| 115 | Bstr bstrPassword;
|
---|
[42395] | 116 | Bstr bstrInitiator;
|
---|
[44131] | 117 | Bstr bstrIso;
|
---|
| 118 | Utf8Str strIso;
|
---|
[34634] | 119 | bool fIntNet = false;
|
---|
| 120 |
|
---|
[23802] | 121 | RTGETOPTUNION ValueUnion;
|
---|
| 122 | RTGETOPTSTATE GetState;
|
---|
| 123 | ComPtr<IMachine> machine;
|
---|
| 124 | ComPtr<IStorageController> storageCtl;
|
---|
| 125 |
|
---|
[23934] | 126 | RTGetOptInit(&GetState, a->argc, a->argv, g_aStorageAttachOptions,
|
---|
[26517] | 127 | RT_ELEMENTS(g_aStorageAttachOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
|
---|
[23802] | 128 |
|
---|
[95140] | 129 | while ( SUCCEEDED(hrc)
|
---|
[23802] | 130 | && (c = RTGetOpt(&GetState, &ValueUnion)))
|
---|
| 131 | {
|
---|
| 132 | switch (c)
|
---|
| 133 | {
|
---|
[23902] | 134 | case 's': // storage controller name
|
---|
[23802] | 135 | {
|
---|
| 136 | if (ValueUnion.psz)
|
---|
[23902] | 137 | pszCtl = ValueUnion.psz;
|
---|
[23802] | 138 | else
|
---|
[95140] | 139 | hrc = E_FAIL;
|
---|
[23802] | 140 | break;
|
---|
| 141 | }
|
---|
| 142 |
|
---|
[23902] | 143 | case 'p': // port
|
---|
[23802] | 144 | {
|
---|
[23902] | 145 | port = ValueUnion.u32;
|
---|
[23802] | 146 | break;
|
---|
| 147 | }
|
---|
| 148 |
|
---|
[23902] | 149 | case 'd': // device
|
---|
[23802] | 150 | {
|
---|
[23902] | 151 | device = ValueUnion.u32;
|
---|
| 152 | break;
|
---|
| 153 | }
|
---|
| 154 |
|
---|
[44131] | 155 | case 'm': // medium <none|emptydrive|additions|uuid|filename|host:<drive>|iSCSI>
|
---|
[23902] | 156 | {
|
---|
[23802] | 157 | if (ValueUnion.psz)
|
---|
[23902] | 158 | pszMedium = ValueUnion.psz;
|
---|
[23802] | 159 | else
|
---|
[95140] | 160 | hrc = E_FAIL;
|
---|
[23802] | 161 | break;
|
---|
| 162 | }
|
---|
| 163 |
|
---|
[23902] | 164 | case 't': // type <dvddrive|hdd|fdd>
|
---|
[23802] | 165 | {
|
---|
[23902] | 166 | if (ValueUnion.psz)
|
---|
[34634] | 167 | {
|
---|
| 168 | if (!RTStrICmp(ValueUnion.psz, "hdd"))
|
---|
| 169 | devTypeRequested = DeviceType_HardDisk;
|
---|
| 170 | else if (!RTStrICmp(ValueUnion.psz, "fdd"))
|
---|
| 171 | devTypeRequested = DeviceType_Floppy;
|
---|
| 172 | else if (!RTStrICmp(ValueUnion.psz, "dvddrive"))
|
---|
| 173 | devTypeRequested = DeviceType_DVD;
|
---|
| 174 | else
|
---|
[92372] | 175 | return errorArgument(Storage::tr("Invalid --type argument '%s'"), ValueUnion.psz);
|
---|
[34634] | 176 | }
|
---|
[23902] | 177 | else
|
---|
[95140] | 178 | hrc = E_FAIL;
|
---|
[23802] | 179 | break;
|
---|
| 180 | }
|
---|
| 181 |
|
---|
[23902] | 182 | case 'h': // passthrough <on|off>
|
---|
[23802] | 183 | {
|
---|
[23902] | 184 | if (ValueUnion.psz)
|
---|
| 185 | pszPassThrough = ValueUnion.psz;
|
---|
| 186 | else
|
---|
[95140] | 187 | hrc = E_FAIL;
|
---|
[23802] | 188 | break;
|
---|
| 189 | }
|
---|
| 190 |
|
---|
[37709] | 191 | case 'e': // tempeject <on|off>
|
---|
| 192 | {
|
---|
| 193 | if (ValueUnion.psz)
|
---|
| 194 | pszTempEject = ValueUnion.psz;
|
---|
| 195 | else
|
---|
[95140] | 196 | hrc = E_FAIL;
|
---|
[37709] | 197 | break;
|
---|
| 198 | }
|
---|
| 199 |
|
---|
[37824] | 200 | case 'n': // nonrotational <on|off>
|
---|
| 201 | {
|
---|
| 202 | if (ValueUnion.psz)
|
---|
| 203 | pszNonRotational = ValueUnion.psz;
|
---|
| 204 | else
|
---|
[95140] | 205 | hrc = E_FAIL;
|
---|
[37824] | 206 | break;
|
---|
| 207 | }
|
---|
| 208 |
|
---|
[48734] | 209 | case 'u': // discard <on|off>
|
---|
[38874] | 210 | {
|
---|
| 211 | if (ValueUnion.psz)
|
---|
| 212 | pszDiscard = ValueUnion.psz;
|
---|
| 213 | else
|
---|
[95140] | 214 | hrc = E_FAIL;
|
---|
[38874] | 215 | break;
|
---|
| 216 | }
|
---|
| 217 |
|
---|
[49190] | 218 | case 'o': // hotpluggable <on|off>
|
---|
| 219 | {
|
---|
| 220 | if (ValueUnion.psz)
|
---|
| 221 | pszHotPluggable = ValueUnion.psz;
|
---|
| 222 | else
|
---|
[95140] | 223 | hrc = E_FAIL;
|
---|
[49190] | 224 | break;
|
---|
| 225 | }
|
---|
| 226 |
|
---|
[34587] | 227 | case 'b': // bandwidthgroup <name>
|
---|
| 228 | {
|
---|
| 229 | if (ValueUnion.psz)
|
---|
| 230 | pszBandwidthGroup = ValueUnion.psz;
|
---|
| 231 | else
|
---|
[95140] | 232 | hrc = E_FAIL;
|
---|
[34587] | 233 | break;
|
---|
| 234 | }
|
---|
| 235 |
|
---|
[24505] | 236 | case 'f': // force unmount medium during runtime
|
---|
[24504] | 237 | {
|
---|
[24505] | 238 | fForceUnmount = true;
|
---|
[24504] | 239 | break;
|
---|
| 240 | }
|
---|
| 241 |
|
---|
[34634] | 242 | case 'C':
|
---|
| 243 | if (ValueUnion.psz)
|
---|
| 244 | bstrComment = ValueUnion.psz;
|
---|
| 245 | else
|
---|
[95140] | 246 | hrc = E_FAIL;
|
---|
[37525] | 247 | break;
|
---|
[34634] | 248 |
|
---|
[37525] | 249 | case 'q':
|
---|
| 250 | if (ValueUnion.psz)
|
---|
| 251 | {
|
---|
| 252 | bstrNewUuid = ValueUnion.psz;
|
---|
| 253 | fSetNewUuid = true;
|
---|
| 254 | }
|
---|
| 255 | else
|
---|
[95140] | 256 | hrc = E_FAIL;
|
---|
[37525] | 257 | break;
|
---|
| 258 |
|
---|
| 259 | case 'Q':
|
---|
| 260 | if (ValueUnion.psz)
|
---|
| 261 | {
|
---|
| 262 | bstrNewParentUuid = ValueUnion.psz;
|
---|
| 263 | fSetNewParentUuid = true;
|
---|
| 264 | }
|
---|
| 265 | else
|
---|
[95140] | 266 | hrc = E_FAIL;
|
---|
[37525] | 267 | break;
|
---|
| 268 |
|
---|
[34634] | 269 | case 'S': // --server
|
---|
| 270 | bstrServer = ValueUnion.psz;
|
---|
| 271 | break;
|
---|
| 272 |
|
---|
| 273 | case 'T': // --target
|
---|
| 274 | bstrTarget = ValueUnion.psz;
|
---|
| 275 | break;
|
---|
| 276 |
|
---|
[37929] | 277 | case 'P': // --tport
|
---|
[34634] | 278 | bstrPort = ValueUnion.psz;
|
---|
| 279 | break;
|
---|
| 280 |
|
---|
| 281 | case 'L': // --lun
|
---|
| 282 | bstrLun = ValueUnion.psz;
|
---|
| 283 | break;
|
---|
| 284 |
|
---|
| 285 | case 'E': // --encodedlun
|
---|
| 286 | bstrLun = BstrFmt("enc%s", ValueUnion.psz);
|
---|
| 287 | break;
|
---|
| 288 |
|
---|
| 289 | case 'U': // --username
|
---|
| 290 | bstrUsername = ValueUnion.psz;
|
---|
| 291 | break;
|
---|
| 292 |
|
---|
| 293 | case 'W': // --password
|
---|
| 294 | bstrPassword = ValueUnion.psz;
|
---|
| 295 | break;
|
---|
| 296 |
|
---|
[69693] | 297 | case 'w': // --passwordFile
|
---|
| 298 | {
|
---|
| 299 | Utf8Str utf8Password;
|
---|
| 300 | RTEXITCODE rcExit = readPasswordFile(ValueUnion.psz, &utf8Password);
|
---|
| 301 | if (rcExit != RTEXITCODE_SUCCESS)
|
---|
[95140] | 302 | hrc = E_FAIL;
|
---|
[69693] | 303 | bstrPassword = utf8Password;
|
---|
| 304 | break;
|
---|
| 305 | }
|
---|
[42395] | 306 | case 'N': // --initiator
|
---|
| 307 | bstrInitiator = ValueUnion.psz;
|
---|
| 308 | break;
|
---|
| 309 |
|
---|
[34634] | 310 | case 'M': // --type
|
---|
| 311 | {
|
---|
[54438] | 312 | int vrc = parseMediumType(ValueUnion.psz, &enmMediumType);
|
---|
[34634] | 313 | if (RT_FAILURE(vrc))
|
---|
[92372] | 314 | return errorArgument(Storage::tr("Invalid medium type '%s'"), ValueUnion.psz);
|
---|
[35136] | 315 | fSetMediumType = true;
|
---|
[34634] | 316 | break;
|
---|
| 317 | }
|
---|
| 318 |
|
---|
| 319 | case 'I': // --intnet
|
---|
| 320 | fIntNet = true;
|
---|
| 321 | break;
|
---|
| 322 |
|
---|
[23802] | 323 | default:
|
---|
| 324 | {
|
---|
[94217] | 325 | errorGetOpt(c, &ValueUnion);
|
---|
[95140] | 326 | hrc = E_FAIL;
|
---|
[23802] | 327 | break;
|
---|
| 328 | }
|
---|
| 329 | }
|
---|
| 330 | }
|
---|
[31008] | 331 |
|
---|
[95140] | 332 | if (FAILED(hrc))
|
---|
[56118] | 333 | return RTEXITCODE_FAILURE;
|
---|
[23802] | 334 |
|
---|
[30125] | 335 | if (!pszCtl)
|
---|
[94217] | 336 | return errorSyntax(Storage::tr("Storage controller name not specified"));
|
---|
[30125] | 337 |
|
---|
[34634] | 338 | // find the machine, lock it, get the mutable session machine
|
---|
[33294] | 339 | CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
|
---|
[56118] | 340 | machine.asOutParam()), RTEXITCODE_FAILURE);
|
---|
| 341 | CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE);
|
---|
[31019] | 342 | SessionType_T st;
|
---|
[56118] | 343 | CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), RTEXITCODE_FAILURE);
|
---|
[23802] | 344 | a->session->COMGETTER(Machine)(machine.asOutParam());
|
---|
| 345 |
|
---|
[101035] | 346 | ComPtr<IPlatform> platform;
|
---|
| 347 | CHECK_ERROR_RET(machine, COMGETTER(Platform)(platform.asOutParam()), RTEXITCODE_FAILURE);
|
---|
| 348 | ComPtr<IPlatformProperties> platformProperties;
|
---|
| 349 | CHECK_ERROR_RET(platform, COMGETTER(Properties)(platformProperties.asOutParam()), RTEXITCODE_FAILURE);
|
---|
| 350 |
|
---|
[34634] | 351 | try
|
---|
[23902] | 352 | {
|
---|
[34634] | 353 | bool fRunTime = (st == SessionType_Shared);
|
---|
[37674] | 354 |
|
---|
[23902] | 355 | if (fRunTime)
|
---|
[23802] | 356 | {
|
---|
[37674] | 357 | if (pszPassThrough)
|
---|
[92372] | 358 | throw Utf8Str(Storage::tr("Drive passthrough state cannot be changed while the VM is running\n"));
|
---|
[34634] | 359 | else if (pszBandwidthGroup)
|
---|
[92372] | 360 | throw Utf8Str(Storage::tr("Bandwidth group cannot be changed while the VM is running\n"));
|
---|
[34634] | 361 | }
|
---|
[23902] | 362 |
|
---|
[34634] | 363 | /* check if the storage controller is present */
|
---|
[95140] | 364 | hrc = machine->GetStorageControllerByName(Bstr(pszCtl).raw(),
|
---|
| 365 | storageCtl.asOutParam());
|
---|
| 366 | if (FAILED(hrc))
|
---|
[92372] | 367 | throw Utf8StrFmt(Storage::tr("Could not find a controller named '%s'\n"), pszCtl);
|
---|
[24504] | 368 |
|
---|
[37929] | 369 | StorageBus_T storageBus = StorageBus_Null;
|
---|
[56118] | 370 | CHECK_ERROR_RET(storageCtl, COMGETTER(Bus)(&storageBus), RTEXITCODE_FAILURE);
|
---|
[37929] | 371 | ULONG maxPorts = 0;
|
---|
[101035] | 372 | CHECK_ERROR_RET(platformProperties, GetMaxPortCountForStorageBus(storageBus, &maxPorts), RTEXITCODE_FAILURE);
|
---|
[37929] | 373 | ULONG maxDevices = 0;
|
---|
[101035] | 374 | CHECK_ERROR_RET(platformProperties, GetMaxDevicesPerPortForStorageBus(storageBus, &maxDevices), RTEXITCODE_FAILURE);
|
---|
[37929] | 375 |
|
---|
| 376 | if (port == ~0U)
|
---|
| 377 | {
|
---|
| 378 | if (maxPorts == 1)
|
---|
| 379 | port = 0;
|
---|
| 380 | else
|
---|
[94217] | 381 | return errorSyntax(Storage::tr("Port not specified"));
|
---|
[37929] | 382 | }
|
---|
| 383 | if (device == ~0U)
|
---|
| 384 | {
|
---|
| 385 | if (maxDevices == 1)
|
---|
| 386 | device = 0;
|
---|
| 387 | else
|
---|
[94217] | 388 | return errorSyntax(Storage::tr("Device not specified"));
|
---|
[37929] | 389 | }
|
---|
| 390 |
|
---|
[34634] | 391 | /* for sata controller check if the port count is big enough
|
---|
| 392 | * to accommodate the current port which is being assigned
|
---|
| 393 | * else just increase the port count
|
---|
| 394 | */
|
---|
[23802] | 395 | {
|
---|
[34634] | 396 | ULONG ulPortCount = 0;
|
---|
| 397 | ULONG ulMaxPortCount = 0;
|
---|
[23902] | 398 |
|
---|
[34634] | 399 | CHECK_ERROR(storageCtl, COMGETTER(MaxPortCount)(&ulMaxPortCount));
|
---|
| 400 | CHECK_ERROR(storageCtl, COMGETTER(PortCount)(&ulPortCount));
|
---|
[23902] | 401 |
|
---|
[34634] | 402 | if ( (ulPortCount != ulMaxPortCount)
|
---|
| 403 | && (port >= ulPortCount)
|
---|
| 404 | && (port < ulMaxPortCount))
|
---|
| 405 | CHECK_ERROR(storageCtl, COMSETTER(PortCount)(port + 1));
|
---|
| 406 | }
|
---|
[24346] | 407 |
|
---|
[34634] | 408 | StorageControllerType_T ctlType = StorageControllerType_Null;
|
---|
| 409 | CHECK_ERROR(storageCtl, COMGETTER(ControllerType)(&ctlType));
|
---|
[23902] | 410 |
|
---|
[34634] | 411 | if (!RTStrICmp(pszMedium, "none"))
|
---|
| 412 | {
|
---|
| 413 | CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl).raw(), port, device));
|
---|
[23902] | 414 | }
|
---|
[34634] | 415 | else if (!RTStrICmp(pszMedium, "emptydrive"))
|
---|
[23963] | 416 | {
|
---|
[34634] | 417 | if (fRunTime)
|
---|
[23963] | 418 | {
|
---|
[34634] | 419 | ComPtr<IMediumAttachment> mediumAttachment;
|
---|
| 420 | DeviceType_T deviceType = DeviceType_Null;
|
---|
[95140] | 421 | hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port, device,
|
---|
| 422 | mediumAttachment.asOutParam());
|
---|
| 423 | if (SUCCEEDED(hrc))
|
---|
[23963] | 424 | {
|
---|
[34634] | 425 | mediumAttachment->COMGETTER(Type)(&deviceType);
|
---|
[23963] | 426 |
|
---|
[34634] | 427 | if ( (deviceType == DeviceType_DVD)
|
---|
| 428 | || (deviceType == DeviceType_Floppy))
|
---|
[23963] | 429 | {
|
---|
[34634] | 430 | /* just unmount the floppy/dvd */
|
---|
[42442] | 431 | CHECK_ERROR(machine, UnmountMedium(Bstr(pszCtl).raw(),
|
---|
| 432 | port,
|
---|
| 433 | device,
|
---|
| 434 | fForceUnmount));
|
---|
[23963] | 435 | }
|
---|
| 436 | }
|
---|
[38330] | 437 | else if (devTypeRequested == DeviceType_DVD)
|
---|
| 438 | {
|
---|
| 439 | /*
|
---|
| 440 | * Try to attach an empty DVD drive as a hotplug operation.
|
---|
| 441 | * Main will complain if the controller doesn't support hotplugging.
|
---|
| 442 | */
|
---|
[42538] | 443 | CHECK_ERROR(machine, AttachDeviceWithoutMedium(Bstr(pszCtl).raw(), port, device,
|
---|
| 444 | devTypeRequested));
|
---|
[38330] | 445 | deviceType = DeviceType_DVD; /* To avoid the error message below. */
|
---|
| 446 | }
|
---|
[23963] | 447 |
|
---|
[95140] | 448 | if ( FAILED(hrc)
|
---|
[34634] | 449 | || !( deviceType == DeviceType_DVD
|
---|
| 450 | || deviceType == DeviceType_Floppy)
|
---|
| 451 | )
|
---|
[92372] | 452 | throw Utf8StrFmt(Storage::tr("No DVD/Floppy Drive attached to the controller '%s'"
|
---|
| 453 | "at the port: %u, device: %u"), pszCtl, port, device);
|
---|
[23902] | 454 |
|
---|
[34634] | 455 | }
|
---|
| 456 | else
|
---|
[24346] | 457 | {
|
---|
[34634] | 458 | DeviceType_T deviceType = DeviceType_Null;
|
---|
| 459 | com::SafeArray <DeviceType_T> saDeviceTypes;
|
---|
[24346] | 460 | ULONG driveCheck = 0;
|
---|
[34634] | 461 |
|
---|
| 462 | /* check if the device type is supported by the controller */
|
---|
[101035] | 463 | CHECK_ERROR(platformProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
|
---|
[24346] | 464 | for (size_t i = 0; i < saDeviceTypes.size(); ++ i)
|
---|
| 465 | {
|
---|
[34634] | 466 | if ( (saDeviceTypes[i] == DeviceType_DVD)
|
---|
| 467 | || (saDeviceTypes[i] == DeviceType_Floppy))
|
---|
[24346] | 468 | driveCheck++;
|
---|
[34634] | 469 | }
|
---|
[24346] | 470 |
|
---|
[34634] | 471 | if (!driveCheck)
|
---|
[92372] | 472 | throw Utf8StrFmt(Storage::tr("The attachment is not supported by the storage controller '%s'"), pszCtl);
|
---|
[24346] | 473 |
|
---|
[34634] | 474 | if (storageBus == StorageBus_Floppy)
|
---|
| 475 | deviceType = DeviceType_Floppy;
|
---|
| 476 | else
|
---|
| 477 | deviceType = DeviceType_DVD;
|
---|
| 478 |
|
---|
| 479 | /* attach a empty floppy/dvd drive after removing previous attachment */
|
---|
| 480 | machine->DetachDevice(Bstr(pszCtl).raw(), port, device);
|
---|
[42538] | 481 | CHECK_ERROR(machine, AttachDeviceWithoutMedium(Bstr(pszCtl).raw(), port, device,
|
---|
| 482 | deviceType));
|
---|
[34634] | 483 | }
|
---|
| 484 | } // end if (!RTStrICmp(pszMedium, "emptydrive"))
|
---|
| 485 | else
|
---|
| 486 | {
|
---|
| 487 | ComPtr<IMedium> pMedium2Mount;
|
---|
| 488 |
|
---|
| 489 | // not "none", not "emptydrive": then it must be a UUID or filename or hostdrive or iSCSI;
|
---|
| 490 | // for all these we first need to know the type of drive we're attaching to
|
---|
| 491 | {
|
---|
| 492 | /*
|
---|
| 493 | * try to determine the type of the drive from the
|
---|
| 494 | * storage controller chipset, the attachment and
|
---|
| 495 | * the medium being attached
|
---|
| 496 | */
|
---|
| 497 | if (ctlType == StorageControllerType_I82078) // floppy controller
|
---|
| 498 | devTypeRequested = DeviceType_Floppy;
|
---|
[37824] | 499 | else
|
---|
[24346] | 500 | {
|
---|
[34634] | 501 | /*
|
---|
| 502 | * for SATA/SCSI/IDE it is hard to tell if it is a harddisk or
|
---|
| 503 | * a dvd being attached so lets check if the medium attachment
|
---|
| 504 | * and the medium, both are of same type. if yes then we are
|
---|
| 505 | * sure of its type and don't need the user to enter it manually
|
---|
| 506 | * else ask the user for the type.
|
---|
| 507 | */
|
---|
| 508 | ComPtr<IMediumAttachment> mediumAttachment;
|
---|
[95140] | 509 | hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port,
|
---|
| 510 | device,
|
---|
| 511 | mediumAttachment.asOutParam());
|
---|
| 512 | if (SUCCEEDED(hrc))
|
---|
[34634] | 513 | {
|
---|
| 514 | DeviceType_T deviceType;
|
---|
| 515 | mediumAttachment->COMGETTER(Type)(&deviceType);
|
---|
| 516 |
|
---|
[37824] | 517 | if (pszMedium)
|
---|
[34634] | 518 | {
|
---|
[44131] | 519 | if (!RTStrICmp(pszMedium, "additions"))
|
---|
| 520 | {
|
---|
| 521 | ComPtr<ISystemProperties> pProperties;
|
---|
| 522 | CHECK_ERROR(a->virtualBox,
|
---|
| 523 | COMGETTER(SystemProperties)(pProperties.asOutParam()));
|
---|
| 524 | CHECK_ERROR(pProperties, COMGETTER(DefaultAdditionsISO)(bstrIso.asOutParam()));
|
---|
| 525 | strIso = Utf8Str(bstrIso);
|
---|
[44132] | 526 | if (strIso.isEmpty())
|
---|
[92372] | 527 | throw Utf8Str(Storage::tr("Cannot find the Guest Additions ISO image\n"));
|
---|
[44131] | 528 | pszMedium = strIso.c_str();
|
---|
| 529 | if (devTypeRequested == DeviceType_Null)
|
---|
| 530 | devTypeRequested = DeviceType_DVD;
|
---|
| 531 | }
|
---|
[37824] | 532 | ComPtr<IMedium> pExistingMedium;
|
---|
[95140] | 533 | hrc = openMedium(a, pszMedium, deviceType,
|
---|
| 534 | AccessMode_ReadWrite,
|
---|
| 535 | pExistingMedium,
|
---|
| 536 | false /* fForceNewUuidOnOpen */,
|
---|
| 537 | true /* fSilent */);
|
---|
| 538 | if (SUCCEEDED(hrc) && pExistingMedium)
|
---|
[37824] | 539 | {
|
---|
| 540 | if ( (deviceType == DeviceType_DVD)
|
---|
| 541 | || (deviceType == DeviceType_HardDisk)
|
---|
| 542 | )
|
---|
| 543 | devTypeRequested = deviceType;
|
---|
| 544 | }
|
---|
[34634] | 545 | }
|
---|
[37824] | 546 | else
|
---|
| 547 | devTypeRequested = deviceType;
|
---|
[34634] | 548 | }
|
---|
[24346] | 549 | }
|
---|
| 550 | }
|
---|
| 551 |
|
---|
[34634] | 552 | if (devTypeRequested == DeviceType_Null) // still the initializer value?
|
---|
[92372] | 553 | throw Utf8Str(Storage::tr("Argument --type must be specified\n"));
|
---|
[23802] | 554 |
|
---|
[34634] | 555 | /* check if the device type is supported by the controller */
|
---|
[23802] | 556 | {
|
---|
[34634] | 557 | com::SafeArray <DeviceType_T> saDeviceTypes;
|
---|
[23802] | 558 |
|
---|
[101035] | 559 | CHECK_ERROR(platformProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
|
---|
[95140] | 560 | if (SUCCEEDED(hrc))
|
---|
[23802] | 561 | {
|
---|
[34634] | 562 | ULONG driveCheck = 0;
|
---|
| 563 | for (size_t i = 0; i < saDeviceTypes.size(); ++ i)
|
---|
| 564 | if (saDeviceTypes[i] == devTypeRequested)
|
---|
| 565 | driveCheck++;
|
---|
| 566 | if (!driveCheck)
|
---|
[92372] | 567 | throw Utf8StrFmt(Storage::tr("The given attachment is not supported by the storage controller '%s'"), pszCtl);
|
---|
[23802] | 568 | }
|
---|
| 569 | else
|
---|
[34634] | 570 | goto leave;
|
---|
[23802] | 571 | }
|
---|
| 572 |
|
---|
[34634] | 573 | // find the medium given
|
---|
| 574 | /* host drive? */
|
---|
[51259] | 575 | if (!RTStrNICmp(pszMedium, RT_STR_TUPLE("host:")))
|
---|
[23802] | 576 | {
|
---|
[34634] | 577 | ComPtr<IHost> host;
|
---|
| 578 | CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
|
---|
| 579 |
|
---|
| 580 | if (devTypeRequested == DeviceType_DVD)
|
---|
[23802] | 581 | {
|
---|
[95140] | 582 | hrc = host->FindHostDVDDrive(Bstr(pszMedium + 5).raw(),
|
---|
| 583 | pMedium2Mount.asOutParam());
|
---|
[34634] | 584 | if (!pMedium2Mount)
|
---|
[23802] | 585 | {
|
---|
| 586 | /* 2nd try: try with the real name, important on Linux+libhal */
|
---|
| 587 | char szPathReal[RTPATH_MAX];
|
---|
[23902] | 588 | if (RT_FAILURE(RTPathReal(pszMedium + 5, szPathReal, sizeof(szPathReal))))
|
---|
[92372] | 589 | throw Utf8StrFmt(Storage::tr("Invalid host DVD drive name \"%s\""), pszMedium + 5);
|
---|
[95140] | 590 | hrc = host->FindHostDVDDrive(Bstr(szPathReal).raw(),
|
---|
| 591 | pMedium2Mount.asOutParam());
|
---|
[34634] | 592 | if (!pMedium2Mount)
|
---|
[92372] | 593 | throw Utf8StrFmt(Storage::tr("Invalid host DVD drive name \"%s\""), pszMedium + 5);
|
---|
[23802] | 594 | }
|
---|
| 595 | }
|
---|
| 596 | else
|
---|
| 597 | {
|
---|
[34634] | 598 | // floppy
|
---|
[95140] | 599 | hrc = host->FindHostFloppyDrive(Bstr(pszMedium + 5).raw(),
|
---|
| 600 | pMedium2Mount.asOutParam());
|
---|
[34634] | 601 | if (!pMedium2Mount)
|
---|
[92372] | 602 | throw Utf8StrFmt(Storage::tr("Invalid host floppy drive name \"%s\""), pszMedium + 5);
|
---|
[23802] | 603 | }
|
---|
[34634] | 604 | }
|
---|
| 605 | else if (!RTStrICmp(pszMedium, "iSCSI"))
|
---|
[23902] | 606 | {
|
---|
[34634] | 607 | /* check for required options */
|
---|
| 608 | if (bstrServer.isEmpty() || bstrTarget.isEmpty())
|
---|
[92372] | 609 | throw Utf8StrFmt(Storage::tr("Parameters --server and --target are required for iSCSI media"));
|
---|
[23802] | 610 |
|
---|
[34634] | 611 | /** @todo move the location stuff to Main, which can use pfnComposeName
|
---|
| 612 | * from the disk backends to construct the location properly. Also do
|
---|
| 613 | * not use slashes to separate the parts, as otherwise only the last
|
---|
| 614 | * element containing information will be shown. */
|
---|
| 615 | Bstr bstrISCSIMedium;
|
---|
| 616 | if ( bstrLun.isEmpty()
|
---|
| 617 | || (bstrLun == "0")
|
---|
| 618 | || (bstrLun == "enc0")
|
---|
| 619 | )
|
---|
| 620 | bstrISCSIMedium = BstrFmt("%ls|%ls", bstrServer.raw(), bstrTarget.raw());
|
---|
| 621 | else
|
---|
| 622 | bstrISCSIMedium = BstrFmt("%ls|%ls|%ls", bstrServer.raw(), bstrTarget.raw(), bstrLun.raw());
|
---|
[23802] | 623 |
|
---|
[54438] | 624 | CHECK_ERROR(a->virtualBox, CreateMedium(Bstr("iSCSI").raw(),
|
---|
| 625 | bstrISCSIMedium.raw(),
|
---|
| 626 | AccessMode_ReadWrite,
|
---|
| 627 | DeviceType_HardDisk,
|
---|
| 628 | pMedium2Mount.asOutParam()));
|
---|
[95140] | 629 | if (FAILED(hrc)) goto leave; /** @todo r=andy Argh!! Why not using exceptions here? */
|
---|
[34634] | 630 | if (!bstrPort.isEmpty())
|
---|
| 631 | bstrServer = BstrFmt("%ls:%ls", bstrServer.raw(), bstrPort.raw());
|
---|
[23802] | 632 |
|
---|
[34634] | 633 | // set the other iSCSI parameters as properties
|
---|
| 634 | com::SafeArray <BSTR> names;
|
---|
| 635 | com::SafeArray <BSTR> values;
|
---|
| 636 | Bstr("TargetAddress").detachTo(names.appendedRaw());
|
---|
| 637 | bstrServer.detachTo(values.appendedRaw());
|
---|
| 638 | Bstr("TargetName").detachTo(names.appendedRaw());
|
---|
| 639 | bstrTarget.detachTo(values.appendedRaw());
|
---|
[23802] | 640 |
|
---|
[34634] | 641 | if (!bstrLun.isEmpty())
|
---|
| 642 | {
|
---|
| 643 | Bstr("LUN").detachTo(names.appendedRaw());
|
---|
| 644 | bstrLun.detachTo(values.appendedRaw());
|
---|
| 645 | }
|
---|
| 646 | if (!bstrUsername.isEmpty())
|
---|
| 647 | {
|
---|
| 648 | Bstr("InitiatorUsername").detachTo(names.appendedRaw());
|
---|
| 649 | bstrUsername.detachTo(values.appendedRaw());
|
---|
| 650 | }
|
---|
| 651 | if (!bstrPassword.isEmpty())
|
---|
| 652 | {
|
---|
| 653 | Bstr("InitiatorSecret").detachTo(names.appendedRaw());
|
---|
| 654 | bstrPassword.detachTo(values.appendedRaw());
|
---|
| 655 | }
|
---|
[43914] | 656 | if (!bstrInitiator.isEmpty())
|
---|
[42395] | 657 | {
|
---|
| 658 | Bstr("InitiatorName").detachTo(names.appendedRaw());
|
---|
| 659 | bstrInitiator.detachTo(values.appendedRaw());
|
---|
| 660 | }
|
---|
[23802] | 661 |
|
---|
[34634] | 662 | /// @todo add --targetName and --targetPassword options
|
---|
[23802] | 663 |
|
---|
[34634] | 664 | if (fIntNet)
|
---|
[23802] | 665 | {
|
---|
[34634] | 666 | Bstr("HostIPStack").detachTo(names.appendedRaw());
|
---|
| 667 | Bstr("0").detachTo(values.appendedRaw());
|
---|
[23802] | 668 | }
|
---|
[34634] | 669 |
|
---|
| 670 | CHECK_ERROR(pMedium2Mount, SetProperties(ComSafeArrayAsInParam(names),
|
---|
| 671 | ComSafeArrayAsInParam(values)));
|
---|
[95140] | 672 | if (FAILED(hrc)) goto leave;
|
---|
[34634] | 673 | Bstr guid;
|
---|
| 674 | CHECK_ERROR(pMedium2Mount, COMGETTER(Id)(guid.asOutParam()));
|
---|
[95140] | 675 | if (FAILED(hrc)) goto leave;
|
---|
[92372] | 676 | RTPrintf(Storage::tr("iSCSI disk created. UUID: %s\n"), Utf8Str(guid).c_str());
|
---|
[23802] | 677 | }
|
---|
| 678 | else
|
---|
| 679 | {
|
---|
[37824] | 680 | if (!pszMedium)
|
---|
| 681 | {
|
---|
| 682 | ComPtr<IMediumAttachment> mediumAttachment;
|
---|
[95140] | 683 | hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port,
|
---|
| 684 | device,
|
---|
| 685 | mediumAttachment.asOutParam());
|
---|
| 686 | if (FAILED(hrc))
|
---|
[92372] | 687 | throw Utf8Str(Storage::tr("Missing --medium argument"));
|
---|
[37824] | 688 | }
|
---|
| 689 | else
|
---|
| 690 | {
|
---|
| 691 | Bstr bstrMedium(pszMedium);
|
---|
[95140] | 692 | hrc = openMedium(a, pszMedium, devTypeRequested,
|
---|
| 693 | AccessMode_ReadWrite, pMedium2Mount,
|
---|
| 694 | fSetNewUuid, false /* fSilent */);
|
---|
| 695 | if (FAILED(hrc) || !pMedium2Mount)
|
---|
[92372] | 696 | throw Utf8StrFmt(Storage::tr("Invalid UUID or filename \"%s\""), pszMedium);
|
---|
[37824] | 697 | }
|
---|
[34634] | 698 | }
|
---|
[23802] | 699 |
|
---|
[37525] | 700 | // set medium/parent medium UUID, if so desired
|
---|
[37824] | 701 | if (pMedium2Mount && (fSetNewUuid || fSetNewParentUuid))
|
---|
[37525] | 702 | {
|
---|
[42551] | 703 | CHECK_ERROR(pMedium2Mount, SetIds(fSetNewUuid, bstrNewUuid.raw(),
|
---|
[37525] | 704 | fSetNewParentUuid, bstrNewParentUuid.raw()));
|
---|
[95140] | 705 | if (FAILED(hrc))
|
---|
[92372] | 706 | throw Utf8Str(Storage::tr("Failed to set the medium/parent medium UUID"));
|
---|
[37525] | 707 | }
|
---|
| 708 |
|
---|
[35115] | 709 | // set medium type, if so desired
|
---|
[35136] | 710 | if (pMedium2Mount && fSetMediumType)
|
---|
[35115] | 711 | {
|
---|
[63257] | 712 | MediumType_T enmMediumTypeOld;
|
---|
| 713 | CHECK_ERROR(pMedium2Mount, COMGETTER(Type)(&enmMediumTypeOld));
|
---|
[95140] | 714 | if (SUCCEEDED(hrc))
|
---|
[63257] | 715 | {
|
---|
| 716 | if (enmMediumTypeOld != enmMediumType)
|
---|
| 717 | {
|
---|
| 718 | CHECK_ERROR(pMedium2Mount, COMSETTER(Type)(enmMediumType));
|
---|
[95140] | 719 | if (FAILED(hrc))
|
---|
[92372] | 720 | throw Utf8Str(Storage::tr("Failed to set the medium type"));
|
---|
[63257] | 721 | }
|
---|
| 722 | }
|
---|
[35115] | 723 | }
|
---|
| 724 |
|
---|
| 725 | if (pMedium2Mount && !bstrComment.isEmpty())
|
---|
| 726 | {
|
---|
| 727 | CHECK_ERROR(pMedium2Mount, COMSETTER(Description)(bstrComment.raw()));
|
---|
| 728 | }
|
---|
| 729 |
|
---|
[37824] | 730 | if (pszMedium)
|
---|
[34634] | 731 | {
|
---|
[37824] | 732 | switch (devTypeRequested)
|
---|
[23902] | 733 | {
|
---|
[37824] | 734 | case DeviceType_DVD:
|
---|
| 735 | case DeviceType_Floppy:
|
---|
[34634] | 736 | {
|
---|
[37824] | 737 | if (!fRunTime)
|
---|
[34634] | 738 | {
|
---|
[37824] | 739 | ComPtr<IMediumAttachment> mediumAttachment;
|
---|
| 740 | // check if there is a dvd/floppy drive at the given location, if not attach one first
|
---|
[95140] | 741 | hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(),
|
---|
| 742 | port,
|
---|
| 743 | device,
|
---|
| 744 | mediumAttachment.asOutParam());
|
---|
| 745 | if (SUCCEEDED(hrc))
|
---|
[34634] | 746 | {
|
---|
[37824] | 747 | DeviceType_T deviceType;
|
---|
| 748 | mediumAttachment->COMGETTER(Type)(&deviceType);
|
---|
| 749 | if (deviceType != devTypeRequested)
|
---|
| 750 | {
|
---|
| 751 | machine->DetachDevice(Bstr(pszCtl).raw(), port, device);
|
---|
[95140] | 752 | hrc = machine->AttachDeviceWithoutMedium(Bstr(pszCtl).raw(),
|
---|
| 753 | port,
|
---|
| 754 | device,
|
---|
| 755 | devTypeRequested); // DeviceType_DVD or DeviceType_Floppy
|
---|
[37824] | 756 | }
|
---|
| 757 | }
|
---|
| 758 | else
|
---|
| 759 | {
|
---|
[95140] | 760 | hrc = machine->AttachDeviceWithoutMedium(Bstr(pszCtl).raw(),
|
---|
| 761 | port,
|
---|
| 762 | device,
|
---|
| 763 | devTypeRequested); // DeviceType_DVD or DeviceType_Floppy
|
---|
[34634] | 764 | }
|
---|
| 765 | }
|
---|
[37824] | 766 |
|
---|
| 767 | if (pMedium2Mount)
|
---|
[34634] | 768 | {
|
---|
[37824] | 769 | CHECK_ERROR(machine, MountMedium(Bstr(pszCtl).raw(),
|
---|
| 770 | port,
|
---|
| 771 | device,
|
---|
| 772 | pMedium2Mount,
|
---|
| 773 | fForceUnmount));
|
---|
[34634] | 774 | }
|
---|
[63300] | 775 | break;
|
---|
[37824] | 776 | } // end DeviceType_DVD or DeviceType_Floppy:
|
---|
[34634] | 777 |
|
---|
[37824] | 778 | case DeviceType_HardDisk:
|
---|
[34634] | 779 | {
|
---|
[37824] | 780 | // if there is anything attached at the given location, remove it
|
---|
| 781 | machine->DetachDevice(Bstr(pszCtl).raw(), port, device);
|
---|
| 782 | CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl).raw(),
|
---|
| 783 | port,
|
---|
| 784 | device,
|
---|
| 785 | DeviceType_HardDisk,
|
---|
| 786 | pMedium2Mount));
|
---|
[63300] | 787 | break;
|
---|
[34634] | 788 | }
|
---|
[63300] | 789 |
|
---|
| 790 | default: break; /* Shut up MSC */
|
---|
[23902] | 791 | }
|
---|
[23802] | 792 | }
|
---|
| 793 | }
|
---|
[34634] | 794 |
|
---|
| 795 | if ( pszPassThrough
|
---|
[95140] | 796 | && (SUCCEEDED(hrc)))
|
---|
[23902] | 797 | {
|
---|
[34634] | 798 | ComPtr<IMediumAttachment> mattach;
|
---|
| 799 | CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port,
|
---|
| 800 | device, mattach.asOutParam()));
|
---|
| 801 |
|
---|
[95140] | 802 | if (SUCCEEDED(hrc))
|
---|
[34634] | 803 | {
|
---|
| 804 | if (!RTStrICmp(pszPassThrough, "on"))
|
---|
| 805 | {
|
---|
| 806 | CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl).raw(),
|
---|
| 807 | port, device, TRUE));
|
---|
| 808 | }
|
---|
| 809 | else if (!RTStrICmp(pszPassThrough, "off"))
|
---|
| 810 | {
|
---|
| 811 | CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl).raw(),
|
---|
| 812 | port, device, FALSE));
|
---|
| 813 | }
|
---|
| 814 | else
|
---|
[92372] | 815 | throw Utf8StrFmt(Storage::tr("Invalid --passthrough argument '%s'"), pszPassThrough);
|
---|
[34634] | 816 | }
|
---|
| 817 | else
|
---|
[92372] | 818 | throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl);
|
---|
[23902] | 819 | }
|
---|
[23802] | 820 |
|
---|
[37709] | 821 | if ( pszTempEject
|
---|
[95140] | 822 | && (SUCCEEDED(hrc)))
|
---|
[37709] | 823 | {
|
---|
| 824 | ComPtr<IMediumAttachment> mattach;
|
---|
| 825 | CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port,
|
---|
| 826 | device, mattach.asOutParam()));
|
---|
| 827 |
|
---|
[95140] | 828 | if (SUCCEEDED(hrc))
|
---|
[37709] | 829 | {
|
---|
| 830 | if (!RTStrICmp(pszTempEject, "on"))
|
---|
| 831 | {
|
---|
| 832 | CHECK_ERROR(machine, TemporaryEjectDevice(Bstr(pszCtl).raw(),
|
---|
| 833 | port, device, TRUE));
|
---|
| 834 | }
|
---|
| 835 | else if (!RTStrICmp(pszTempEject, "off"))
|
---|
| 836 | {
|
---|
| 837 | CHECK_ERROR(machine, TemporaryEjectDevice(Bstr(pszCtl).raw(),
|
---|
| 838 | port, device, FALSE));
|
---|
| 839 | }
|
---|
| 840 | else
|
---|
[92372] | 841 | throw Utf8StrFmt(Storage::tr("Invalid --tempeject argument '%s'"), pszTempEject);
|
---|
[37709] | 842 | }
|
---|
| 843 | else
|
---|
[92372] | 844 | throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl);
|
---|
[37709] | 845 | }
|
---|
| 846 |
|
---|
[37824] | 847 | if ( pszNonRotational
|
---|
[95140] | 848 | && (SUCCEEDED(hrc)))
|
---|
[37824] | 849 | {
|
---|
| 850 | ComPtr<IMediumAttachment> mattach;
|
---|
| 851 | CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port,
|
---|
| 852 | device, mattach.asOutParam()));
|
---|
| 853 |
|
---|
[95140] | 854 | if (SUCCEEDED(hrc))
|
---|
[37824] | 855 | {
|
---|
| 856 | if (!RTStrICmp(pszNonRotational, "on"))
|
---|
| 857 | {
|
---|
| 858 | CHECK_ERROR(machine, NonRotationalDevice(Bstr(pszCtl).raw(),
|
---|
| 859 | port, device, TRUE));
|
---|
| 860 | }
|
---|
| 861 | else if (!RTStrICmp(pszNonRotational, "off"))
|
---|
| 862 | {
|
---|
| 863 | CHECK_ERROR(machine, NonRotationalDevice(Bstr(pszCtl).raw(),
|
---|
| 864 | port, device, FALSE));
|
---|
| 865 | }
|
---|
| 866 | else
|
---|
[92372] | 867 | throw Utf8StrFmt(Storage::tr("Invalid --nonrotational argument '%s'"), pszNonRotational);
|
---|
[37824] | 868 | }
|
---|
| 869 | else
|
---|
[92372] | 870 | throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl);
|
---|
[37824] | 871 | }
|
---|
| 872 |
|
---|
[43531] | 873 | if ( pszDiscard
|
---|
[95140] | 874 | && (SUCCEEDED(hrc)))
|
---|
[38874] | 875 | {
|
---|
| 876 | ComPtr<IMediumAttachment> mattach;
|
---|
| 877 | CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port,
|
---|
| 878 | device, mattach.asOutParam()));
|
---|
| 879 |
|
---|
[95140] | 880 | if (SUCCEEDED(hrc))
|
---|
[38874] | 881 | {
|
---|
| 882 | if (!RTStrICmp(pszDiscard, "on"))
|
---|
| 883 | {
|
---|
[38887] | 884 | CHECK_ERROR(machine, SetAutoDiscardForDevice(Bstr(pszCtl).raw(),
|
---|
| 885 | port, device, TRUE));
|
---|
[38874] | 886 | }
|
---|
| 887 | else if (!RTStrICmp(pszDiscard, "off"))
|
---|
| 888 | {
|
---|
[38887] | 889 | CHECK_ERROR(machine, SetAutoDiscardForDevice(Bstr(pszCtl).raw(),
|
---|
| 890 | port, device, FALSE));
|
---|
[38874] | 891 | }
|
---|
| 892 | else
|
---|
[92372] | 893 | throw Utf8StrFmt(Storage::tr("Invalid --discard argument '%s'"), pszDiscard);
|
---|
[38874] | 894 | }
|
---|
| 895 | else
|
---|
[92372] | 896 | throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl);
|
---|
[38874] | 897 | }
|
---|
| 898 |
|
---|
[49190] | 899 | if ( pszHotPluggable
|
---|
[95140] | 900 | && (SUCCEEDED(hrc)))
|
---|
[49190] | 901 | {
|
---|
| 902 | ComPtr<IMediumAttachment> mattach;
|
---|
| 903 | CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port,
|
---|
| 904 | device, mattach.asOutParam()));
|
---|
[38874] | 905 |
|
---|
[95140] | 906 | if (SUCCEEDED(hrc))
|
---|
[49190] | 907 | {
|
---|
| 908 | if (!RTStrICmp(pszHotPluggable, "on"))
|
---|
| 909 | {
|
---|
| 910 | CHECK_ERROR(machine, SetHotPluggableForDevice(Bstr(pszCtl).raw(),
|
---|
| 911 | port, device, TRUE));
|
---|
| 912 | }
|
---|
| 913 | else if (!RTStrICmp(pszHotPluggable, "off"))
|
---|
| 914 | {
|
---|
| 915 | CHECK_ERROR(machine, SetHotPluggableForDevice(Bstr(pszCtl).raw(),
|
---|
| 916 | port, device, FALSE));
|
---|
| 917 | }
|
---|
| 918 | else
|
---|
[92372] | 919 | throw Utf8StrFmt(Storage::tr("Invalid --hotpluggable argument '%s'"), pszHotPluggable);
|
---|
[49190] | 920 | }
|
---|
| 921 | else
|
---|
[92372] | 922 | throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl);
|
---|
[49190] | 923 | }
|
---|
| 924 |
|
---|
[34634] | 925 | if ( pszBandwidthGroup
|
---|
| 926 | && !fRunTime
|
---|
[95140] | 927 | && SUCCEEDED(hrc))
|
---|
[34634] | 928 | {
|
---|
[23902] | 929 |
|
---|
[34634] | 930 | if (!RTStrICmp(pszBandwidthGroup, "none"))
|
---|
[23902] | 931 | {
|
---|
[34634] | 932 | /* Just remove the bandwidth gorup. */
|
---|
[42538] | 933 | CHECK_ERROR(machine, SetNoBandwidthGroupForDevice(Bstr(pszCtl).raw(),
|
---|
| 934 | port, device));
|
---|
[23902] | 935 | }
|
---|
| 936 | else
|
---|
| 937 | {
|
---|
[34634] | 938 | ComPtr<IBandwidthControl> bwCtrl;
|
---|
| 939 | ComPtr<IBandwidthGroup> bwGroup;
|
---|
[23902] | 940 |
|
---|
[34634] | 941 | CHECK_ERROR(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()));
|
---|
[34587] | 942 |
|
---|
[95140] | 943 | if (SUCCEEDED(hrc))
|
---|
[34587] | 944 | {
|
---|
[34634] | 945 | CHECK_ERROR(bwCtrl, GetBandwidthGroup(Bstr(pszBandwidthGroup).raw(), bwGroup.asOutParam()));
|
---|
[95140] | 946 | if (SUCCEEDED(hrc))
|
---|
[34634] | 947 | {
|
---|
| 948 | CHECK_ERROR(machine, SetBandwidthGroupForDevice(Bstr(pszCtl).raw(),
|
---|
| 949 | port, device, bwGroup));
|
---|
| 950 | }
|
---|
[34587] | 951 | }
|
---|
| 952 | }
|
---|
| 953 | }
|
---|
[34634] | 954 |
|
---|
| 955 | /* commit changes */
|
---|
[95140] | 956 | if (SUCCEEDED(hrc))
|
---|
[34634] | 957 | CHECK_ERROR(machine, SaveSettings());
|
---|
[34587] | 958 | }
|
---|
[34634] | 959 | catch (const Utf8Str &strError)
|
---|
| 960 | {
|
---|
| 961 | errorArgument("%s", strError.c_str());
|
---|
[95140] | 962 | hrc = E_FAIL;
|
---|
[34634] | 963 | }
|
---|
[34587] | 964 |
|
---|
[34634] | 965 | // machine must always be unlocked, even on errors
|
---|
[23902] | 966 | leave:
|
---|
[31070] | 967 | a->session->UnlockMachine();
|
---|
[23802] | 968 |
|
---|
[95140] | 969 | return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
|
---|
[23802] | 970 | }
|
---|
| 971 |
|
---|
| 972 |
|
---|
| 973 | static const RTGETOPTDEF g_aStorageControllerOptions[] =
|
---|
| 974 | {
|
---|
[23809] | 975 | { "--name", 'n', RTGETOPT_REQ_STRING },
|
---|
[23802] | 976 | { "--add", 'a', RTGETOPT_REQ_STRING },
|
---|
[23902] | 977 | { "--controller", 'c', RTGETOPT_REQ_STRING },
|
---|
[48985] | 978 | { "--portcount", 'p', RTGETOPT_REQ_UINT32 },
|
---|
[23802] | 979 | { "--remove", 'r', RTGETOPT_REQ_NOTHING },
|
---|
[56821] | 980 | { "--rename", 'R', RTGETOPT_REQ_STRING },
|
---|
[29480] | 981 | { "--hostiocache", 'i', RTGETOPT_REQ_STRING },
|
---|
[34010] | 982 | { "--bootable", 'b', RTGETOPT_REQ_STRING },
|
---|
[23802] | 983 | };
|
---|
| 984 |
|
---|
[56118] | 985 | RTEXITCODE handleStorageController(HandlerArg *a)
|
---|
[23802] | 986 | {
|
---|
| 987 | int c;
|
---|
| 988 | const char *pszCtl = NULL;
|
---|
| 989 | const char *pszBusType = NULL;
|
---|
| 990 | const char *pszCtlType = NULL;
|
---|
[29480] | 991 | const char *pszHostIOCache = NULL;
|
---|
[34010] | 992 | const char *pszBootable = NULL;
|
---|
[56821] | 993 | const char *pszCtlNewName = NULL;
|
---|
[48985] | 994 | ULONG portcount = ~0U;
|
---|
[23802] | 995 | bool fRemoveCtl = false;
|
---|
| 996 | ComPtr<IMachine> machine;
|
---|
| 997 | RTGETOPTUNION ValueUnion;
|
---|
| 998 | RTGETOPTSTATE GetState;
|
---|
| 999 |
|
---|
| 1000 | if (a->argc < 4)
|
---|
[94179] | 1001 | return errorSyntax(Storage::tr("Too few parameters"));
|
---|
[23802] | 1002 |
|
---|
| 1003 | RTGetOptInit (&GetState, a->argc, a->argv, g_aStorageControllerOptions,
|
---|
[26517] | 1004 | RT_ELEMENTS(g_aStorageControllerOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
|
---|
[23802] | 1005 |
|
---|
[56118] | 1006 | while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
|
---|
[23802] | 1007 | {
|
---|
| 1008 | switch (c)
|
---|
| 1009 | {
|
---|
[23809] | 1010 | case 'n': // controller name
|
---|
[56118] | 1011 | Assert(ValueUnion.psz);
|
---|
| 1012 | pszCtl = ValueUnion.psz;
|
---|
[23802] | 1013 | break;
|
---|
| 1014 |
|
---|
| 1015 | case 'a': // controller bus type <ide/sata/scsi/floppy>
|
---|
[56118] | 1016 | Assert(ValueUnion.psz);
|
---|
| 1017 | pszBusType = ValueUnion.psz;
|
---|
[23802] | 1018 | break;
|
---|
| 1019 |
|
---|
[23902] | 1020 | case 'c': // controller <lsilogic/buslogic/intelahci/piix3/piix4/ich6/i82078>
|
---|
[56118] | 1021 | Assert(ValueUnion.psz);
|
---|
| 1022 | pszCtlType = ValueUnion.psz;
|
---|
[23802] | 1023 | break;
|
---|
| 1024 |
|
---|
[48985] | 1025 | case 'p': // portcount
|
---|
| 1026 | portcount = ValueUnion.u32;
|
---|
[23802] | 1027 | break;
|
---|
| 1028 |
|
---|
| 1029 | case 'r': // remove controller
|
---|
| 1030 | fRemoveCtl = true;
|
---|
| 1031 | break;
|
---|
| 1032 |
|
---|
[56821] | 1033 | case 'R': // rename controller
|
---|
| 1034 | Assert(ValueUnion.psz);
|
---|
| 1035 | pszCtlNewName = ValueUnion.psz;
|
---|
| 1036 | break;
|
---|
| 1037 |
|
---|
[28764] | 1038 | case 'i':
|
---|
[29480] | 1039 | pszHostIOCache = ValueUnion.psz;
|
---|
[28764] | 1040 | break;
|
---|
| 1041 |
|
---|
[34010] | 1042 | case 'b':
|
---|
| 1043 | pszBootable = ValueUnion.psz;
|
---|
| 1044 | break;
|
---|
| 1045 |
|
---|
[23802] | 1046 | default:
|
---|
[94179] | 1047 | return errorGetOpt(c, &ValueUnion);
|
---|
[23802] | 1048 | }
|
---|
| 1049 | }
|
---|
| 1050 |
|
---|
[95140] | 1051 | HRESULT hrc;
|
---|
[23802] | 1052 |
|
---|
| 1053 | /* try to find the given machine */
|
---|
[33294] | 1054 | CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
|
---|
[56118] | 1055 | machine.asOutParam()), RTEXITCODE_FAILURE);
|
---|
[23802] | 1056 |
|
---|
| 1057 | /* open a session for the VM */
|
---|
[56118] | 1058 | CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE);
|
---|
[23802] | 1059 |
|
---|
| 1060 | /* get the mutable session machine */
|
---|
| 1061 | a->session->COMGETTER(Machine)(machine.asOutParam());
|
---|
| 1062 |
|
---|
| 1063 | if (!pszCtl)
|
---|
| 1064 | {
|
---|
[23902] | 1065 | /* it's important to always close sessions */
|
---|
[31070] | 1066 | a->session->UnlockMachine();
|
---|
[94179] | 1067 | return errorSyntax(Storage::tr("Storage controller name not specified\n"));
|
---|
[23802] | 1068 | }
|
---|
| 1069 |
|
---|
| 1070 | if (fRemoveCtl)
|
---|
| 1071 | {
|
---|
[42017] | 1072 | CHECK_ERROR(machine, RemoveStorageController(Bstr(pszCtl).raw()));
|
---|
[23802] | 1073 | }
|
---|
| 1074 | else
|
---|
| 1075 | {
|
---|
| 1076 | if (pszBusType)
|
---|
| 1077 | {
|
---|
| 1078 | ComPtr<IStorageController> ctl;
|
---|
| 1079 |
|
---|
| 1080 | if (!RTStrICmp(pszBusType, "ide"))
|
---|
| 1081 | {
|
---|
[32718] | 1082 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1083 | StorageBus_IDE,
|
---|
| 1084 | ctl.asOutParam()));
|
---|
[23802] | 1085 | }
|
---|
| 1086 | else if (!RTStrICmp(pszBusType, "sata"))
|
---|
| 1087 | {
|
---|
[32718] | 1088 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1089 | StorageBus_SATA,
|
---|
| 1090 | ctl.asOutParam()));
|
---|
[23802] | 1091 | }
|
---|
| 1092 | else if (!RTStrICmp(pszBusType, "scsi"))
|
---|
| 1093 | {
|
---|
[32718] | 1094 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1095 | StorageBus_SCSI,
|
---|
| 1096 | ctl.asOutParam()));
|
---|
[23802] | 1097 | }
|
---|
| 1098 | else if (!RTStrICmp(pszBusType, "floppy"))
|
---|
| 1099 | {
|
---|
[32718] | 1100 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1101 | StorageBus_Floppy,
|
---|
| 1102 | ctl.asOutParam()));
|
---|
[23802] | 1103 | }
|
---|
[25589] | 1104 | else if (!RTStrICmp(pszBusType, "sas"))
|
---|
| 1105 | {
|
---|
[32718] | 1106 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1107 | StorageBus_SAS,
|
---|
| 1108 | ctl.asOutParam()));
|
---|
[25589] | 1109 | }
|
---|
[48983] | 1110 | else if (!RTStrICmp(pszBusType, "usb"))
|
---|
| 1111 | {
|
---|
| 1112 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1113 | StorageBus_USB,
|
---|
| 1114 | ctl.asOutParam()));
|
---|
| 1115 | }
|
---|
[57525] | 1116 | else if (!RTStrICmp(pszBusType, "pcie"))
|
---|
| 1117 | {
|
---|
| 1118 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1119 | StorageBus_PCIe,
|
---|
| 1120 | ctl.asOutParam()));
|
---|
| 1121 | }
|
---|
[78512] | 1122 | else if (!RTStrICmp(pszBusType, "virtio-scsi") || !RTStrICmp(pszBusType, "virtio"))
|
---|
| 1123 | {
|
---|
| 1124 | CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
|
---|
| 1125 | StorageBus_VirtioSCSI,
|
---|
| 1126 | ctl.asOutParam()));
|
---|
| 1127 | }
|
---|
[23802] | 1128 | else
|
---|
| 1129 | {
|
---|
[92372] | 1130 | errorArgument(Storage::tr("Invalid --add argument '%s'"), pszBusType);
|
---|
[95140] | 1131 | hrc = E_FAIL;
|
---|
[23802] | 1132 | }
|
---|
| 1133 | }
|
---|
| 1134 |
|
---|
| 1135 | if ( pszCtlType
|
---|
[95140] | 1136 | && SUCCEEDED(hrc))
|
---|
[23802] | 1137 | {
|
---|
| 1138 | ComPtr<IStorageController> ctl;
|
---|
| 1139 |
|
---|
[32718] | 1140 | CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
|
---|
| 1141 | ctl.asOutParam()));
|
---|
[23802] | 1142 |
|
---|
[95140] | 1143 | if (SUCCEEDED(hrc))
|
---|
[23802] | 1144 | {
|
---|
| 1145 | if (!RTStrICmp(pszCtlType, "lsilogic"))
|
---|
| 1146 | {
|
---|
[23934] | 1147 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogic));
|
---|
[23802] | 1148 | }
|
---|
| 1149 | else if (!RTStrICmp(pszCtlType, "buslogic"))
|
---|
| 1150 | {
|
---|
[23934] | 1151 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic));
|
---|
[23802] | 1152 | }
|
---|
| 1153 | else if (!RTStrICmp(pszCtlType, "intelahci"))
|
---|
| 1154 | {
|
---|
[23934] | 1155 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_IntelAhci));
|
---|
[23802] | 1156 | }
|
---|
| 1157 | else if (!RTStrICmp(pszCtlType, "piix3"))
|
---|
| 1158 | {
|
---|
[23934] | 1159 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX3));
|
---|
[23802] | 1160 | }
|
---|
| 1161 | else if (!RTStrICmp(pszCtlType, "piix4"))
|
---|
| 1162 | {
|
---|
[23934] | 1163 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX4));
|
---|
[23802] | 1164 | }
|
---|
| 1165 | else if (!RTStrICmp(pszCtlType, "ich6"))
|
---|
| 1166 | {
|
---|
[23934] | 1167 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_ICH6));
|
---|
[23802] | 1168 | }
|
---|
| 1169 | else if (!RTStrICmp(pszCtlType, "i82078"))
|
---|
| 1170 | {
|
---|
[23934] | 1171 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_I82078));
|
---|
[23802] | 1172 | }
|
---|
[25676] | 1173 | else if (!RTStrICmp(pszCtlType, "lsilogicsas"))
|
---|
[25589] | 1174 | {
|
---|
| 1175 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogicSas));
|
---|
| 1176 | }
|
---|
[48983] | 1177 | else if (!RTStrICmp(pszCtlType, "usb"))
|
---|
| 1178 | {
|
---|
| 1179 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_USB));
|
---|
| 1180 | }
|
---|
[57525] | 1181 | else if (!RTStrICmp(pszCtlType, "nvme"))
|
---|
| 1182 | {
|
---|
| 1183 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_NVMe));
|
---|
| 1184 | }
|
---|
[78512] | 1185 | else if (!RTStrICmp(pszCtlType, "virtio-scsi") || !RTStrICmp(pszCtlType, "virtio"))
|
---|
| 1186 | {
|
---|
| 1187 | CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_VirtioSCSI));
|
---|
| 1188 | }
|
---|
[23802] | 1189 | else
|
---|
| 1190 | {
|
---|
[92372] | 1191 | errorArgument(Storage::tr("Invalid --type argument '%s'"), pszCtlType);
|
---|
[95140] | 1192 | hrc = E_FAIL;
|
---|
[23802] | 1193 | }
|
---|
| 1194 | }
|
---|
| 1195 | else
|
---|
| 1196 | {
|
---|
[92372] | 1197 | errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl);
|
---|
[95140] | 1198 | hrc = E_FAIL;
|
---|
[23802] | 1199 | }
|
---|
| 1200 | }
|
---|
| 1201 |
|
---|
[48985] | 1202 | if ( (portcount != ~0U)
|
---|
[95140] | 1203 | && SUCCEEDED(hrc))
|
---|
[23802] | 1204 | {
|
---|
| 1205 | ComPtr<IStorageController> ctl;
|
---|
| 1206 |
|
---|
[32718] | 1207 | CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
|
---|
| 1208 | ctl.asOutParam()));
|
---|
[23802] | 1209 |
|
---|
[95140] | 1210 | if (SUCCEEDED(hrc))
|
---|
[23802] | 1211 | {
|
---|
[48985] | 1212 | CHECK_ERROR(ctl, COMSETTER(PortCount)(portcount));
|
---|
[23802] | 1213 | }
|
---|
| 1214 | else
|
---|
| 1215 | {
|
---|
[92372] | 1216 | errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl);
|
---|
[95140] | 1217 | hrc = E_FAIL; /** @todo r=andy Overwrites original hrc. */
|
---|
[23802] | 1218 | }
|
---|
| 1219 | }
|
---|
| 1220 |
|
---|
[29480] | 1221 | if ( pszHostIOCache
|
---|
[95140] | 1222 | && SUCCEEDED(hrc))
|
---|
[28764] | 1223 | {
|
---|
[29480] | 1224 | ComPtr<IStorageController> ctl;
|
---|
[28764] | 1225 |
|
---|
[32718] | 1226 | CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
|
---|
| 1227 | ctl.asOutParam()));
|
---|
[28764] | 1228 |
|
---|
[95140] | 1229 | if (SUCCEEDED(hrc))
|
---|
[29480] | 1230 | {
|
---|
[30403] | 1231 | if (!RTStrICmp(pszHostIOCache, "on"))
|
---|
| 1232 | {
|
---|
| 1233 | CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(TRUE));
|
---|
| 1234 | }
|
---|
| 1235 | else if (!RTStrICmp(pszHostIOCache, "off"))
|
---|
| 1236 | {
|
---|
| 1237 | CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(FALSE));
|
---|
| 1238 | }
|
---|
| 1239 | else
|
---|
| 1240 | {
|
---|
[92372] | 1241 | errorArgument(Storage::tr("Invalid --hostiocache argument '%s'"), pszHostIOCache);
|
---|
[95140] | 1242 | hrc = E_FAIL;
|
---|
[30403] | 1243 | }
|
---|
[29480] | 1244 | }
|
---|
| 1245 | else
|
---|
| 1246 | {
|
---|
[92372] | 1247 | errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl);
|
---|
[95140] | 1248 | hrc = E_FAIL; /** @todo r=andy Ditto. */
|
---|
[29480] | 1249 | }
|
---|
[28764] | 1250 | }
|
---|
[34010] | 1251 |
|
---|
| 1252 | if ( pszBootable
|
---|
[95140] | 1253 | && SUCCEEDED(hrc))
|
---|
[34010] | 1254 | {
|
---|
[95140] | 1255 | if (SUCCEEDED(hrc))
|
---|
[34010] | 1256 | {
|
---|
| 1257 | if (!RTStrICmp(pszBootable, "on"))
|
---|
| 1258 | {
|
---|
| 1259 | CHECK_ERROR(machine, SetStorageControllerBootable(Bstr(pszCtl).raw(), TRUE));
|
---|
| 1260 | }
|
---|
| 1261 | else if (!RTStrICmp(pszBootable, "off"))
|
---|
| 1262 | {
|
---|
| 1263 | CHECK_ERROR(machine, SetStorageControllerBootable(Bstr(pszCtl).raw(), FALSE));
|
---|
| 1264 | }
|
---|
| 1265 | else
|
---|
| 1266 | {
|
---|
[92372] | 1267 | errorArgument(Storage::tr("Invalid --bootable argument '%s'"), pszBootable);
|
---|
[95140] | 1268 | hrc = E_FAIL;
|
---|
[34010] | 1269 | }
|
---|
| 1270 | }
|
---|
| 1271 | else
|
---|
| 1272 | {
|
---|
[92372] | 1273 | errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl);
|
---|
[95140] | 1274 | hrc = E_FAIL;
|
---|
[34010] | 1275 | }
|
---|
| 1276 | }
|
---|
[56821] | 1277 |
|
---|
| 1278 | if ( pszCtlNewName
|
---|
[95140] | 1279 | && SUCCEEDED(hrc))
|
---|
[56821] | 1280 | {
|
---|
| 1281 | ComPtr<IStorageController> ctl;
|
---|
| 1282 |
|
---|
| 1283 | CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
|
---|
| 1284 | ctl.asOutParam()));
|
---|
| 1285 |
|
---|
[95140] | 1286 | if (SUCCEEDED(hrc))
|
---|
[56821] | 1287 | {
|
---|
| 1288 | CHECK_ERROR(ctl, COMSETTER(Name)(Bstr(pszCtlNewName).raw()));
|
---|
| 1289 | }
|
---|
| 1290 | else
|
---|
| 1291 | {
|
---|
[92372] | 1292 | errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl);
|
---|
[95140] | 1293 | hrc = E_FAIL;
|
---|
[56821] | 1294 | }
|
---|
| 1295 | }
|
---|
| 1296 |
|
---|
[23802] | 1297 | }
|
---|
| 1298 |
|
---|
| 1299 | /* commit changes */
|
---|
[95140] | 1300 | if (SUCCEEDED(hrc))
|
---|
[23934] | 1301 | CHECK_ERROR(machine, SaveSettings());
|
---|
[23802] | 1302 |
|
---|
| 1303 | /* it's important to always close sessions */
|
---|
[31070] | 1304 | a->session->UnlockMachine();
|
---|
[23802] | 1305 |
|
---|
[95140] | 1306 | return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
|
---|
[23802] | 1307 | }
|
---|