VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp@ 16802

Last change on this file since 16802 was 16530, checked in by vboxsync, 16 years ago

Main: rework error macros everywhere; make error messages much more readable (esp. with VBoxManage); use shared function to actually print message; reduces size of VBoxManage debug build from 3.4 to 2.3 MB

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.4 KB
Line 
1/* $Id: VBoxManageDisk.cpp 16530 2009-02-05 16:08:49Z vboxsync $ */
2/** @file
3 * VBoxManage - The disk delated commands.
4 */
5
6/*
7 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#ifndef VBOX_ONLY_DOCS
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include <VBox/com/com.h>
28#include <VBox/com/array.h>
29#include <VBox/com/ErrorInfo.h>
30#include <VBox/com/errorprint2.h>
31#include <VBox/com/VirtualBox.h>
32
33#include <iprt/asm.h>
34#include <iprt/file.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <VBox/log.h>
38#include <VBox/VBoxHDD-new.h>
39
40#include "VBoxManage.h"
41using namespace com;
42
43
44// funcs
45///////////////////////////////////////////////////////////////////////////////
46
47
48static DECLCALLBACK(void) handleVDError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
49{
50 RTPrintf("ERROR: ");
51 RTPrintfV(pszFormat, va);
52 RTPrintf("\n");
53 RTPrintf("Error code %Rrc at %s(%u) in function %s\n", rc, RT_SRC_POS_ARGS);
54}
55
56
57int handleCreateHardDisk(HandlerArg *a)
58{
59 HRESULT rc;
60 Bstr filename;
61 uint64_t sizeMB = 0;
62 Bstr format = "VDI";
63 bool fStatic = false;
64 Bstr comment;
65 bool fRegister = false;
66 const char *type = "normal";
67
68 /* let's have a closer look at the arguments */
69 for (int i = 0; i < a->argc; i++)
70 {
71 if (strcmp(a->argv[i], "-filename") == 0)
72 {
73 if (a->argc <= i + 1)
74 return errorArgument("Missing argument to '%s'", a->argv[i]);
75 i++;
76 filename = a->argv[i];
77 }
78 else if (strcmp(a->argv[i], "-size") == 0)
79 {
80 if (a->argc <= i + 1)
81 return errorArgument("Missing argument to '%s'", a->argv[i]);
82 i++;
83 sizeMB = RTStrToUInt64(a->argv[i]);
84 }
85 else if (strcmp(a->argv[i], "-format") == 0)
86 {
87 if (a->argc <= i + 1)
88 return errorArgument("Missing argument to '%s'", a->argv[i]);
89 i++;
90 format = a->argv[i];
91 }
92 else if (strcmp(a->argv[i], "-static") == 0)
93 {
94 fStatic = true;
95 }
96 else if (strcmp(a->argv[i], "-comment") == 0)
97 {
98 if (a->argc <= i + 1)
99 return errorArgument("Missing argument to '%s'", a->argv[i]);
100 i++;
101 comment = a->argv[i];
102 }
103 else if (strcmp(a->argv[i], "-register") == 0)
104 {
105 fRegister = true;
106 }
107 else if (strcmp(a->argv[i], "-type") == 0)
108 {
109 if (a->argc <= i + 1)
110 return errorArgument("Missing argument to '%s'", a->argv[i]);
111 i++;
112 type = a->argv[i];
113 }
114 else
115 return errorSyntax(USAGE_CREATEHD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
116 }
117 /* check the outcome */
118 if (!filename || (sizeMB == 0))
119 return errorSyntax(USAGE_CREATEHD, "Parameters -filename and -size are required");
120
121 if (strcmp(type, "normal") && strcmp(type, "writethrough"))
122 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(type).raw());
123
124 ComPtr<IHardDisk2> hardDisk;
125 CHECK_ERROR(a->virtualBox, CreateHardDisk2(format, filename, hardDisk.asOutParam()));
126 if (SUCCEEDED(rc) && hardDisk)
127 {
128 /* we will close the hard disk after the storage has been successfully
129 * created unless fRegister is set */
130 bool doClose = false;
131
132 if (!comment.isNull())
133 {
134 CHECK_ERROR(hardDisk,COMSETTER(Description)(comment));
135 }
136 ComPtr<IProgress> progress;
137 if (fStatic)
138 {
139 CHECK_ERROR(hardDisk, CreateFixedStorage(sizeMB, progress.asOutParam()));
140 }
141 else
142 {
143 CHECK_ERROR(hardDisk, CreateDynamicStorage(sizeMB, progress.asOutParam()));
144 }
145 if (SUCCEEDED(rc) && progress)
146 {
147 if (fStatic)
148 showProgress(progress);
149 else
150 CHECK_ERROR(progress, WaitForCompletion(-1));
151 if (SUCCEEDED(rc))
152 {
153 progress->COMGETTER(ResultCode)(&rc);
154 if (FAILED(rc))
155 {
156 com::ProgressErrorInfo info(progress);
157 if (info.isBasicAvailable())
158 RTPrintf("Error: failed to create hard disk. Error message: %lS\n", info.getText().raw());
159 else
160 RTPrintf("Error: failed to create hard disk. No error message available!\n");
161 }
162 else
163 {
164 doClose = !fRegister;
165
166 Guid uuid;
167 CHECK_ERROR(hardDisk, COMGETTER(Id)(uuid.asOutParam()));
168
169 if (strcmp(type, "normal") == 0)
170 {
171 /* nothing required, default */
172 }
173 else if (strcmp(type, "writethrough") == 0)
174 {
175 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
176 }
177
178 RTPrintf("Disk image created. UUID: %s\n", uuid.toString().raw());
179 }
180 }
181 }
182 if (doClose)
183 {
184 CHECK_ERROR(hardDisk, Close());
185 }
186 }
187 return SUCCEEDED(rc) ? 0 : 1;
188}
189
190#if 0 /* disabled until disk shrinking is implemented based on VBoxHDD-new */
191static DECLCALLBACK(int) hardDiskProgressCallback(PVM pVM, unsigned uPercent, void *pvUser)
192{
193 unsigned *pPercent = (unsigned *)pvUser;
194
195 if (*pPercent != uPercent)
196 {
197 *pPercent = uPercent;
198 RTPrintf(".");
199 if ((uPercent % 10) == 0 && uPercent)
200 RTPrintf("%d%%", uPercent);
201 RTStrmFlush(g_pStdOut);
202 }
203
204 return VINF_SUCCESS;
205}
206#endif
207
208
209int handleModifyHardDisk(HandlerArg *a)
210{
211 HRESULT rc;
212
213 /* The uuid/filename and a command */
214 if (a->argc < 2)
215 return errorSyntax(USAGE_MODIFYHD, "Incorrect number of parameters");
216
217 ComPtr<IHardDisk2> hardDisk;
218 Bstr filepath;
219
220 /* first guess is that it's a UUID */
221 Guid uuid(a->argv[0]);
222 rc = a->virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());
223 /* no? then it must be a filename */
224 if (!hardDisk)
225 {
226 filepath = a->argv[0];
227 CHECK_ERROR(a->virtualBox, FindHardDisk2(filepath, hardDisk.asOutParam()));
228 }
229
230 /* let's find out which command */
231 if (strcmp(a->argv[1], "settype") == 0)
232 {
233 /* hard disk must be registered */
234 if (SUCCEEDED(rc) && hardDisk)
235 {
236 char *type = NULL;
237
238 if (a->argc <= 2)
239 return errorArgument("Missing argument to for settype");
240
241 type = a->argv[2];
242
243 HardDiskType_T hddType;
244 CHECK_ERROR(hardDisk, COMGETTER(Type)(&hddType));
245
246 if (strcmp(type, "normal") == 0)
247 {
248 if (hddType != HardDiskType_Normal)
249 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));
250 }
251 else if (strcmp(type, "writethrough") == 0)
252 {
253 if (hddType != HardDiskType_Writethrough)
254 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
255
256 }
257 else if (strcmp(type, "immutable") == 0)
258 {
259 if (hddType != HardDiskType_Immutable)
260 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));
261 }
262 else
263 {
264 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(type).raw());
265 }
266 }
267 else
268 return errorArgument("Hard disk image not registered");
269 }
270 else if (strcmp(a->argv[1], "compact") == 0)
271 {
272#if 1
273 RTPrintf("Error: Shrink hard disk operation is not implemented!\n");
274 return 1;
275#else
276 /* the hard disk image might not be registered */
277 if (!hardDisk)
278 {
279 a->virtualBox->OpenHardDisk2(Bstr(a->argv[0]), hardDisk.asOutParam());
280 if (!hardDisk)
281 return errorArgument("Hard disk image not found");
282 }
283
284 Bstr format;
285 hardDisk->COMGETTER(Format)(format.asOutParam());
286 if (format != "VDI")
287 return errorArgument("Invalid hard disk type. The command only works on VDI files\n");
288
289 Bstr fileName;
290 hardDisk->COMGETTER(Location)(fileName.asOutParam());
291
292 /* make sure the object reference is released */
293 hardDisk = NULL;
294
295 unsigned uProcent;
296
297 RTPrintf("Shrinking '%lS': 0%%", fileName.raw());
298 int vrc = VDIShrinkImage(Utf8Str(fileName).raw(), hardDiskProgressCallback, &uProcent);
299 if (RT_FAILURE(vrc))
300 {
301 RTPrintf("Error while shrinking hard disk image: %Rrc\n", vrc);
302 rc = E_FAIL;
303 }
304#endif
305 }
306 else
307 return errorSyntax(USAGE_MODIFYHD, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
308
309 return SUCCEEDED(rc) ? 0 : 1;
310}
311
312int handleCloneHardDisk(HandlerArg *a)
313{
314 Bstr src, dst;
315 Bstr format;
316 bool remember = false;
317
318 HRESULT rc;
319
320 /* Parse the arguments. */
321 for (int i = 0; i < a->argc; i++)
322 {
323 if (strcmp(a->argv[i], "-format") == 0)
324 {
325 if (a->argc <= i + 1)
326 {
327 return errorArgument("Missing argument to '%s'", a->argv[i]);
328 }
329 i++;
330 format = a->argv[i];
331 }
332 else if (strcmp(a->argv[i], "-remember") == 0 ||
333 strcmp(a->argv[i], "-register") == 0 /* backward compatiblity */)
334 {
335 remember = true;
336 }
337 else if (src.isEmpty())
338 {
339 src = a->argv[i];
340 }
341 else if (dst.isEmpty())
342 {
343 dst = a->argv[i];
344 }
345 else
346 {
347 return errorSyntax(USAGE_CLONEHD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
348 }
349 }
350
351 if (src.isEmpty())
352 return errorSyntax(USAGE_CLONEHD, "Mandatory UUID or input file parameter missing");
353 if (dst.isEmpty())
354 return errorSyntax(USAGE_CLONEHD, "Mandatory output file parameter missing");
355
356 ComPtr<IHardDisk2> srcDisk;
357 ComPtr<IHardDisk2> dstDisk;
358 bool unknown = false;
359
360 /* first guess is that it's a UUID */
361 Guid uuid(Utf8Str(src).raw());
362 rc = a->virtualBox->GetHardDisk2(uuid, srcDisk.asOutParam());
363 /* no? then it must be a filename */
364 if (FAILED (rc))
365 {
366 rc = a->virtualBox->FindHardDisk2(src, srcDisk.asOutParam());
367 /* no? well, then it's an unkwnown image */
368 if (FAILED (rc))
369 {
370 CHECK_ERROR(a->virtualBox, OpenHardDisk2(src, srcDisk.asOutParam()));
371 if (SUCCEEDED (rc))
372 {
373 unknown = true;
374 }
375 }
376 }
377
378 do
379 {
380 if (!SUCCEEDED(rc))
381 break;
382
383 if (format.isEmpty())
384 {
385 /* get the format of the source hard disk */
386 CHECK_ERROR_BREAK(srcDisk, COMGETTER(Format) (format.asOutParam()));
387 }
388
389 CHECK_ERROR_BREAK(a->virtualBox, CreateHardDisk2(format, dst, dstDisk.asOutParam()));
390
391 ComPtr<IProgress> progress;
392 CHECK_ERROR_BREAK(srcDisk, CloneTo(dstDisk, progress.asOutParam()));
393
394 showProgress(progress);
395 progress->COMGETTER(ResultCode)(&rc);
396 if (FAILED(rc))
397 {
398 com::ProgressErrorInfo info(progress);
399 if (info.isBasicAvailable())
400 RTPrintf("Error: failed to clone hard disk. Error message: %lS\n", info.getText().raw());
401 else
402 RTPrintf("Error: failed to clone hard disk. No error message available!\n");
403 break;
404 }
405
406 CHECK_ERROR_BREAK(dstDisk, COMGETTER(Id)(uuid.asOutParam()));
407
408 RTPrintf("Clone hard disk created in format '%ls'. UUID: %s\n",
409 format.raw(), uuid.toString().raw());
410 }
411 while (0);
412
413 if (!remember && !dstDisk.isNull())
414 {
415 /* forget the created clone */
416 dstDisk->Close();
417 }
418
419 if (unknown)
420 {
421 /* close the unknown hard disk to forget it again */
422 srcDisk->Close();
423 }
424
425 return SUCCEEDED(rc) ? 0 : 1;
426}
427
428int handleConvertFromRaw(int argc, char *argv[])
429{
430 VDIMAGETYPE enmImgType = VD_IMAGE_TYPE_NORMAL;
431 bool fReadFromStdIn = false;
432 const char *format = "VDI";
433 const char *srcfilename = NULL;
434 const char *dstfilename = NULL;
435 const char *filesize = NULL;
436 unsigned uImageFlags = 0; /**< @todo allow creation of non-default image variants */
437 void *pvBuf = NULL;
438
439 for (int i = 0; i < argc; i++)
440 {
441 if (!strcmp(argv[i], "-static"))
442 {
443 enmImgType = VD_IMAGE_TYPE_FIXED;
444 }
445 else if (strcmp(argv[i], "-format") == 0)
446 {
447 if (argc <= i + 1)
448 {
449 return errorArgument("Missing argument to '%s'", argv[i]);
450 }
451 i++;
452 format = argv[i];
453 }
454 else
455 {
456 if (srcfilename)
457 {
458 if (dstfilename)
459 {
460 if (fReadFromStdIn && !filesize)
461 filesize = argv[i];
462 else
463 return errorSyntax(USAGE_CONVERTFROMRAW, "Incorrect number of parameters");
464 }
465 else
466 dstfilename = argv[i];
467 }
468 else
469 {
470 srcfilename = argv[i];
471#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
472 fReadFromStdIn = !strcmp(srcfilename, "stdin");
473#endif
474 }
475 }
476 }
477
478 if (!srcfilename || !dstfilename || (fReadFromStdIn && !filesize))
479 return errorSyntax(USAGE_CONVERTFROMRAW, "Incorrect number of parameters");
480 RTPrintf("Converting from raw image file=\"%s\" to file=\"%s\"...\n",
481 srcfilename, dstfilename);
482
483 int rc = VINF_SUCCESS;
484 PVBOXHDD pDisk = NULL;
485
486 PVDINTERFACE pVDIfs = NULL;
487 VDINTERFACE vdInterfaceError;
488 VDINTERFACEERROR vdInterfaceErrorCallbacks;
489 vdInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
490 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
491 vdInterfaceErrorCallbacks.pfnError = handleVDError;
492
493 rc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
494 &vdInterfaceErrorCallbacks, NULL, &pVDIfs);
495 AssertRC(rc);
496
497 /* open raw image file. */
498 RTFILE File;
499 if (fReadFromStdIn)
500 File = 0;
501 else
502 rc = RTFileOpen(&File, srcfilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
503 if (RT_FAILURE(rc))
504 {
505 RTPrintf("File=\"%s\" open error: %Rrf\n", srcfilename, rc);
506 goto out;
507 }
508
509 uint64_t cbFile;
510 /* get image size. */
511 if (fReadFromStdIn)
512 cbFile = RTStrToUInt64(filesize);
513 else
514 rc = RTFileGetSize(File, &cbFile);
515 if (RT_FAILURE(rc))
516 {
517 RTPrintf("Error getting image size for file \"%s\": %Rrc\n", srcfilename, rc);
518 goto out;
519 }
520
521 RTPrintf("Creating %s image with size %RU64 bytes (%RU64MB)...\n", (enmImgType == VD_IMAGE_TYPE_FIXED) ? "fixed" : "dynamic", cbFile, (cbFile + _1M - 1) / _1M);
522 char pszComment[256];
523 RTStrPrintf(pszComment, sizeof(pszComment), "Converted image from %s", srcfilename);
524 rc = VDCreate(pVDIfs, &pDisk);
525 if (RT_FAILURE(rc))
526 {
527 RTPrintf("Error while creating the virtual disk container: %Rrc\n", rc);
528 goto out;
529 }
530
531 Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) -
532 (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0);
533 PDMMEDIAGEOMETRY PCHS, LCHS;
534 PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383);
535 PCHS.cHeads = 16;
536 PCHS.cSectors = 63;
537 LCHS.cCylinders = 0;
538 LCHS.cHeads = 0;
539 LCHS.cSectors = 0;
540 rc = VDCreateBase(pDisk, format, dstfilename, enmImgType, cbFile,
541 uImageFlags, pszComment, &PCHS, &LCHS, NULL,
542 VD_OPEN_FLAGS_NORMAL, NULL, NULL);
543 if (RT_FAILURE(rc))
544 {
545 RTPrintf("Error while creating the disk image \"%s\": %Rrc\n", dstfilename, rc);
546 goto out;
547 }
548
549 size_t cbBuffer;
550 cbBuffer = _1M;
551 pvBuf = RTMemAlloc(cbBuffer);
552 if (!pvBuf)
553 {
554 rc = VERR_NO_MEMORY;
555 RTPrintf("Not enough memory allocating buffers for image \"%s\": %Rrc\n", dstfilename, rc);
556 goto out;
557 }
558
559 uint64_t offFile;
560 offFile = 0;
561 while (offFile < cbFile)
562 {
563 size_t cbRead;
564 size_t cbToRead;
565 cbRead = 0;
566 cbToRead = cbFile - offFile >= (uint64_t)cbBuffer ?
567 cbBuffer : (size_t) (cbFile - offFile);
568 rc = RTFileRead(File, pvBuf, cbToRead, &cbRead);
569 if (RT_FAILURE(rc) || !cbRead)
570 break;
571 rc = VDWrite(pDisk, offFile, pvBuf, cbRead);
572 if (RT_FAILURE(rc))
573 {
574 RTPrintf("Failed to write to disk image \"%s\": %Rrc\n", dstfilename, rc);
575 goto out;
576 }
577 offFile += cbRead;
578 }
579
580out:
581 if (pvBuf)
582 RTMemFree(pvBuf);
583 if (pDisk)
584 VDClose(pDisk, RT_FAILURE(rc));
585 if (File != NIL_RTFILE)
586 RTFileClose(File);
587
588 return RT_FAILURE(rc);
589}
590
591int handleAddiSCSIDisk(HandlerArg *a)
592{
593 HRESULT rc;
594 Bstr server;
595 Bstr target;
596 Bstr port;
597 Bstr lun;
598 Bstr username;
599 Bstr password;
600 Bstr comment;
601 bool fIntNet = false;
602
603 /* at least server and target */
604 if (a->argc < 4)
605 return errorSyntax(USAGE_ADDISCSIDISK, "Not enough parameters");
606
607 /* let's have a closer look at the arguments */
608 for (int i = 0; i < a->argc; i++)
609 {
610 if (strcmp(a->argv[i], "-server") == 0)
611 {
612 if (a->argc <= i + 1)
613 return errorArgument("Missing argument to '%s'", a->argv[i]);
614 i++;
615 server = a->argv[i];
616 }
617 else if (strcmp(a->argv[i], "-target") == 0)
618 {
619 if (a->argc <= i + 1)
620 return errorArgument("Missing argument to '%s'", a->argv[i]);
621 i++;
622 target = a->argv[i];
623 }
624 else if (strcmp(a->argv[i], "-port") == 0)
625 {
626 if (a->argc <= i + 1)
627 return errorArgument("Missing argument to '%s'", a->argv[i]);
628 i++;
629 port = a->argv[i];
630 }
631 else if (strcmp(a->argv[i], "-lun") == 0)
632 {
633 if (a->argc <= i + 1)
634 return errorArgument("Missing argument to '%s'", a->argv[i]);
635 i++;
636 lun = a->argv[i];
637 }
638 else if (strcmp(a->argv[i], "-encodedlun") == 0)
639 {
640 if (a->argc <= i + 1)
641 return errorArgument("Missing argument to '%s'", a->argv[i]);
642 i++;
643 lun = BstrFmt("enc%s", a->argv[i]);
644 }
645 else if (strcmp(a->argv[i], "-username") == 0)
646 {
647 if (a->argc <= i + 1)
648 return errorArgument("Missing argument to '%s'", a->argv[i]);
649 i++;
650 username = a->argv[i];
651 }
652 else if (strcmp(a->argv[i], "-password") == 0)
653 {
654 if (a->argc <= i + 1)
655 return errorArgument("Missing argument to '%s'", a->argv[i]);
656 i++;
657 password = a->argv[i];
658 }
659 else if (strcmp(a->argv[i], "-comment") == 0)
660 {
661 if (a->argc <= i + 1)
662 return errorArgument("Missing argument to '%s'", a->argv[i]);
663 i++;
664 comment = a->argv[i];
665 }
666 else if (strcmp(a->argv[i], "-intnet") == 0)
667 {
668 i++;
669 fIntNet = true;
670 }
671 else
672 return errorSyntax(USAGE_ADDISCSIDISK, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
673 }
674
675 /* check for required options */
676 if (!server || !target)
677 return errorSyntax(USAGE_ADDISCSIDISK, "Parameters -server and -target are required");
678
679 do
680 {
681 ComPtr<IHardDisk2> hardDisk;
682 CHECK_ERROR_BREAK (a->virtualBox,
683 CreateHardDisk2(Bstr ("iSCSI"),
684 BstrFmt ("%ls/%ls", server.raw(), target.raw()),
685 hardDisk.asOutParam()));
686 CheckComRCBreakRC (rc);
687
688 if (!comment.isNull())
689 CHECK_ERROR_BREAK(hardDisk, COMSETTER(Description)(comment));
690
691 if (!port.isNull())
692 server = BstrFmt ("%ls:%ls", server.raw(), port.raw());
693
694 com::SafeArray <BSTR> names;
695 com::SafeArray <BSTR> values;
696
697 Bstr ("TargetAddress").detachTo (names.appendedRaw());
698 server.detachTo (values.appendedRaw());
699 Bstr ("TargetName").detachTo (names.appendedRaw());
700 target.detachTo (values.appendedRaw());
701
702 if (!lun.isNull())
703 {
704 Bstr ("LUN").detachTo (names.appendedRaw());
705 lun.detachTo (values.appendedRaw());
706 }
707 if (!username.isNull())
708 {
709 Bstr ("InitiatorUsername").detachTo (names.appendedRaw());
710 username.detachTo (values.appendedRaw());
711 }
712 if (!password.isNull())
713 {
714 Bstr ("InitiatorSecret").detachTo (names.appendedRaw());
715 password.detachTo (values.appendedRaw());
716 }
717
718 /// @todo add -initiator option
719 Bstr ("InitiatorName").detachTo (names.appendedRaw());
720 Bstr ("iqn.2008-04.com.sun.virtualbox.initiator").detachTo (values.appendedRaw());
721
722 /// @todo add -targetName and -targetPassword options
723
724 if (fIntNet)
725 {
726 Bstr ("HostIPStack").detachTo (names.appendedRaw());
727 Bstr ("0").detachTo (values.appendedRaw());
728 }
729
730 CHECK_ERROR_BREAK (hardDisk,
731 SetProperties (ComSafeArrayAsInParam (names),
732 ComSafeArrayAsInParam (values)));
733
734 Guid guid;
735 CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));
736 RTPrintf("iSCSI disk created. UUID: %s\n", guid.toString().raw());
737 }
738 while (0);
739
740 return SUCCEEDED(rc) ? 0 : 1;
741}
742
743
744int handleShowHardDiskInfo(HandlerArg *a)
745{
746 HRESULT rc;
747
748 if (a->argc != 1)
749 return errorSyntax(USAGE_SHOWHDINFO, "Incorrect number of parameters");
750
751 ComPtr<IHardDisk2> hardDisk;
752 Bstr filepath;
753
754 bool unknown = false;
755
756 /* first guess is that it's a UUID */
757 Guid uuid(a->argv[0]);
758 rc = a->virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());
759 /* no? then it must be a filename */
760 if (FAILED (rc))
761 {
762 filepath = a->argv[0];
763 rc = a->virtualBox->FindHardDisk2(filepath, hardDisk.asOutParam());
764 /* no? well, then it's an unkwnown image */
765 if (FAILED (rc))
766 {
767 CHECK_ERROR(a->virtualBox, OpenHardDisk2(filepath, hardDisk.asOutParam()));
768 if (SUCCEEDED (rc))
769 {
770 unknown = true;
771 }
772 }
773 }
774 do
775 {
776 if (!SUCCEEDED(rc))
777 break;
778
779 hardDisk->COMGETTER(Id)(uuid.asOutParam());
780 RTPrintf("UUID: %s\n", uuid.toString().raw());
781
782 /* check for accessibility */
783 /// @todo NEWMEDIA check accessibility of all parents
784 /// @todo NEWMEDIA print the full state value
785 MediaState_T state;
786 CHECK_ERROR_BREAK (hardDisk, COMGETTER(State)(&state));
787 RTPrintf("Accessible: %s\n", state != MediaState_Inaccessible ? "yes" : "no");
788
789 if (state == MediaState_Inaccessible)
790 {
791 Bstr err;
792 CHECK_ERROR_BREAK (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()));
793 RTPrintf("Access Error: %lS\n", err.raw());
794 }
795
796 Bstr description;
797 hardDisk->COMGETTER(Description)(description.asOutParam());
798 if (description)
799 {
800 RTPrintf("Description: %lS\n", description.raw());
801 }
802
803 ULONG64 logicalSize;
804 hardDisk->COMGETTER(LogicalSize)(&logicalSize);
805 RTPrintf("Logical size: %llu MBytes\n", logicalSize);
806 ULONG64 actualSize;
807 hardDisk->COMGETTER(Size)(&actualSize);
808 RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
809
810 HardDiskType_T type;
811 hardDisk->COMGETTER(Type)(&type);
812 const char *typeStr = "unknown";
813 switch (type)
814 {
815 case HardDiskType_Normal:
816 typeStr = "normal";
817 break;
818 case HardDiskType_Immutable:
819 typeStr = "immutable";
820 break;
821 case HardDiskType_Writethrough:
822 typeStr = "writethrough";
823 break;
824 }
825 RTPrintf("Type: %s\n", typeStr);
826
827 Bstr format;
828 hardDisk->COMGETTER(Format)(format.asOutParam());
829 RTPrintf("Storage format: %lS\n", format.raw());
830
831 if (!unknown)
832 {
833 com::SafeGUIDArray machineIds;
834 hardDisk->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds));
835 for (size_t j = 0; j < machineIds.size(); ++ j)
836 {
837 ComPtr<IMachine> machine;
838 CHECK_ERROR(a->virtualBox, GetMachine(machineIds[j], machine.asOutParam()));
839 ASSERT(machine);
840 Bstr name;
841 machine->COMGETTER(Name)(name.asOutParam());
842 machine->COMGETTER(Id)(uuid.asOutParam());
843 RTPrintf("%s%lS (UUID: %RTuuid)\n",
844 j == 0 ? "In use by VMs: " : " ",
845 name.raw(), &machineIds[j]);
846 }
847 /// @todo NEWMEDIA check usage in snapshots too
848 /// @todo NEWMEDIA also list children and say 'differencing' for
849 /// hard disks with the parent or 'base' otherwise.
850 }
851
852 Bstr loc;
853 hardDisk->COMGETTER(Location)(loc.asOutParam());
854 RTPrintf("Location: %lS\n", loc.raw());
855 }
856 while (0);
857
858 if (unknown)
859 {
860 /* close the unknown hard disk to forget it again */
861 hardDisk->Close();
862 }
863
864 return SUCCEEDED(rc) ? 0 : 1;
865}
866
867int handleOpenMedium(HandlerArg *a)
868{
869 HRESULT rc;
870
871 if (a->argc < 2)
872 return errorSyntax(USAGE_REGISTERIMAGE, "Not enough parameters");
873
874 Bstr filepath(a->argv[1]);
875
876 if (strcmp(a->argv[0], "disk") == 0)
877 {
878 const char *type = NULL;
879 /* there can be a type parameter */
880 if ((a->argc > 2) && (a->argc != 4))
881 return errorSyntax(USAGE_REGISTERIMAGE, "Incorrect number of parameters");
882 if (a->argc == 4)
883 {
884 if (strcmp(a->argv[2], "-type") != 0)
885 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[2]).raw());
886 if ( (strcmp(a->argv[3], "normal") != 0)
887 && (strcmp(a->argv[3], "immutable") != 0)
888 && (strcmp(a->argv[3], "writethrough") != 0))
889 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(a->argv[3]).raw());
890 type = a->argv[3];
891 }
892
893 ComPtr<IHardDisk2> hardDisk;
894 CHECK_ERROR(a->virtualBox, OpenHardDisk2(filepath, hardDisk.asOutParam()));
895 if (SUCCEEDED(rc) && hardDisk)
896 {
897 /* change the type if requested */
898 if (type)
899 {
900 if (strcmp(type, "normal") == 0)
901 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));
902 else if (strcmp(type, "immutable") == 0)
903 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));
904 else if (strcmp(type, "writethrough") == 0)
905 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
906 }
907 }
908 }
909 else if (strcmp(a->argv[0], "dvd") == 0)
910 {
911 ComPtr<IDVDImage2> dvdImage;
912 CHECK_ERROR(a->virtualBox, OpenDVDImage(filepath, Guid(), dvdImage.asOutParam()));
913 }
914 else if (strcmp(a->argv[0], "floppy") == 0)
915 {
916 ComPtr<IFloppyImage2> floppyImage;
917 CHECK_ERROR(a->virtualBox, OpenFloppyImage(filepath, Guid(), floppyImage.asOutParam()));
918 }
919 else
920 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
921
922 return SUCCEEDED(rc) ? 0 : 1;
923}
924
925int handleCloseMedium(HandlerArg *a)
926{
927 HRESULT rc;
928
929 if (a->argc != 2)
930 return errorSyntax(USAGE_UNREGISTERIMAGE, "Incorrect number of parameters");
931
932 /* first guess is that it's a UUID */
933 Guid uuid(a->argv[1]);
934
935 if (strcmp(a->argv[0], "disk") == 0)
936 {
937 ComPtr<IHardDisk2> hardDisk;
938 rc = a->virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());
939 /* not a UUID or not registered? Then it must be a filename */
940 if (!hardDisk)
941 {
942 CHECK_ERROR(a->virtualBox, FindHardDisk2(Bstr(a->argv[1]), hardDisk.asOutParam()));
943 }
944 if (SUCCEEDED(rc) && hardDisk)
945 {
946 CHECK_ERROR(hardDisk, Close());
947 }
948 }
949 else
950 if (strcmp(a->argv[0], "dvd") == 0)
951 {
952 ComPtr<IDVDImage2> dvdImage;
953 rc = a->virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
954 /* not a UUID or not registered? Then it must be a filename */
955 if (!dvdImage)
956 {
957 CHECK_ERROR(a->virtualBox, FindDVDImage(Bstr(a->argv[1]), dvdImage.asOutParam()));
958 }
959 if (SUCCEEDED(rc) && dvdImage)
960 {
961 CHECK_ERROR(dvdImage, Close());
962 }
963 }
964 else
965 if (strcmp(a->argv[0], "floppy") == 0)
966 {
967 ComPtr<IFloppyImage2> floppyImage;
968 rc = a->virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
969 /* not a UUID or not registered? Then it must be a filename */
970 if (!floppyImage)
971 {
972 CHECK_ERROR(a->virtualBox, FindFloppyImage(Bstr(a->argv[1]), floppyImage.asOutParam()));
973 }
974 if (SUCCEEDED(rc) && floppyImage)
975 {
976 CHECK_ERROR(floppyImage, Close());
977 }
978 }
979 else
980 return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
981
982 return SUCCEEDED(rc) ? 0 : 1;
983}
984#endif /* !VBOX_ONLY_DOCS */
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