VirtualBox

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

Last change on this file since 16107 was 16052, checked in by vboxsync, 16 years ago

FE/VBoxManage: Don't hold COM objects past XPCOM shutdown; pack all handler arguments to a single structure.

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