VirtualBox

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

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

VBoxManage: Print "normal (base)" for root hard disks and "normal (differencing)" for differencing ones. Print the auto-reset state for differencing hard disks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.5 KB
Line 
1/* $Id: VBoxManageDisk.cpp 17654 2009-03-10 23:55:28Z 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.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<IHardDisk> hardDisk;
125 CHECK_ERROR(a->virtualBox, CreateHardDisk(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 */
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<IHardDisk> hardDisk;
218 Bstr filepath;
219
220 /* first guess is that it's a UUID */
221 Guid uuid(a->argv[0]);
222 rc = a->virtualBox->GetHardDisk(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, FindHardDisk(filepath, hardDisk.asOutParam()));
228 if (FAILED(rc))
229 return 1;
230 }
231
232 /* let's find out which command */
233 if (strcmp(a->argv[1], "settype") == 0)
234 {
235 /* hard disk must be registered */
236 if (SUCCEEDED(rc) && hardDisk)
237 {
238 char *type = NULL;
239
240 if (a->argc <= 2)
241 return errorArgument("Missing argument for settype");
242
243 type = a->argv[2];
244
245 HardDiskType_T hddType;
246 CHECK_ERROR(hardDisk, COMGETTER(Type)(&hddType));
247
248 if (strcmp(type, "normal") == 0)
249 {
250 if (hddType != HardDiskType_Normal)
251 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));
252 }
253 else if (strcmp(type, "writethrough") == 0)
254 {
255 if (hddType != HardDiskType_Writethrough)
256 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
257
258 }
259 else if (strcmp(type, "immutable") == 0)
260 {
261 if (hddType != HardDiskType_Immutable)
262 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));
263 }
264 else
265 {
266 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(type).raw());
267 }
268 }
269 else
270 return errorArgument("Hard disk image not registered");
271 }
272 else if (strcmp(a->argv[1], "autoreset") == 0)
273 {
274 char *onOff = NULL;
275
276 if (a->argc <= 2)
277 return errorArgument("Missing argument for autoreset");
278
279 onOff = a->argv[2];
280
281 if (strcmp(onOff, "on") == 0)
282 {
283 CHECK_ERROR(hardDisk, COMSETTER(AutoReset)(TRUE));
284 }
285 else if (strcmp(onOff, "off") == 0)
286 {
287 CHECK_ERROR(hardDisk, COMSETTER(AutoReset)(FALSE));
288 }
289 else
290 {
291 return errorArgument("Invalid autoreset argument '%s' specified",
292 Utf8Str(onOff).raw());
293 }
294 }
295 else if (strcmp(a->argv[1], "compact") == 0)
296 {
297#if 1
298 RTPrintf("Error: Shrink hard disk operation is not implemented!\n");
299 return 1;
300#else
301 /* the hard disk image might not be registered */
302 if (!hardDisk)
303 {
304 a->virtualBox->OpenHardDisk(Bstr(a->argv[0]), hardDisk.asOutParam());
305 if (!hardDisk)
306 return errorArgument("Hard disk image not found");
307 }
308
309 Bstr format;
310 hardDisk->COMGETTER(Format)(format.asOutParam());
311 if (format != "VDI")
312 return errorArgument("Invalid hard disk type. The command only works on VDI files\n");
313
314 Bstr fileName;
315 hardDisk->COMGETTER(Location)(fileName.asOutParam());
316
317 /* make sure the object reference is released */
318 hardDisk = NULL;
319
320 unsigned uProcent;
321
322 RTPrintf("Shrinking '%lS': 0%%", fileName.raw());
323 int vrc = VDIShrinkImage(Utf8Str(fileName).raw(), hardDiskProgressCallback, &uProcent);
324 if (RT_FAILURE(vrc))
325 {
326 RTPrintf("Error while shrinking hard disk image: %Rrc\n", vrc);
327 rc = E_FAIL;
328 }
329#endif
330 }
331 else
332 return errorSyntax(USAGE_MODIFYHD, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
333
334 return SUCCEEDED(rc) ? 0 : 1;
335}
336
337int handleCloneHardDisk(HandlerArg *a)
338{
339 Bstr src, dst;
340 Bstr format;
341 bool remember = false;
342
343 HRESULT rc;
344
345 /* Parse the arguments. */
346 for (int i = 0; i < a->argc; i++)
347 {
348 if (strcmp(a->argv[i], "-format") == 0)
349 {
350 if (a->argc <= i + 1)
351 {
352 return errorArgument("Missing argument to '%s'", a->argv[i]);
353 }
354 i++;
355 format = a->argv[i];
356 }
357 else if (strcmp(a->argv[i], "-remember") == 0 ||
358 strcmp(a->argv[i], "-register") == 0 /* backward compatiblity */)
359 {
360 remember = true;
361 }
362 else if (src.isEmpty())
363 {
364 src = a->argv[i];
365 }
366 else if (dst.isEmpty())
367 {
368 dst = a->argv[i];
369 }
370 else
371 {
372 return errorSyntax(USAGE_CLONEHD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
373 }
374 }
375
376 if (src.isEmpty())
377 return errorSyntax(USAGE_CLONEHD, "Mandatory UUID or input file parameter missing");
378 if (dst.isEmpty())
379 return errorSyntax(USAGE_CLONEHD, "Mandatory output file parameter missing");
380
381 ComPtr<IHardDisk> srcDisk;
382 ComPtr<IHardDisk> dstDisk;
383 bool unknown = false;
384
385 /* first guess is that it's a UUID */
386 Guid uuid(Utf8Str(src).raw());
387 rc = a->virtualBox->GetHardDisk(uuid, srcDisk.asOutParam());
388 /* no? then it must be a filename */
389 if (FAILED (rc))
390 {
391 rc = a->virtualBox->FindHardDisk(src, srcDisk.asOutParam());
392 /* no? well, then it's an unkwnown image */
393 if (FAILED (rc))
394 {
395 CHECK_ERROR(a->virtualBox, OpenHardDisk(src, srcDisk.asOutParam()));
396 if (SUCCEEDED (rc))
397 {
398 unknown = true;
399 }
400 }
401 }
402
403 do
404 {
405 if (!SUCCEEDED(rc))
406 break;
407
408 if (format.isEmpty())
409 {
410 /* get the format of the source hard disk */
411 CHECK_ERROR_BREAK(srcDisk, COMGETTER(Format) (format.asOutParam()));
412 }
413
414 CHECK_ERROR_BREAK(a->virtualBox, CreateHardDisk(format, dst, dstDisk.asOutParam()));
415
416 ComPtr<IProgress> progress;
417 CHECK_ERROR_BREAK(srcDisk, CloneTo(dstDisk, progress.asOutParam()));
418
419 showProgress(progress);
420 progress->COMGETTER(ResultCode)(&rc);
421 if (FAILED(rc))
422 {
423 com::ProgressErrorInfo info(progress);
424 if (info.isBasicAvailable())
425 RTPrintf("Error: failed to clone hard disk. Error message: %lS\n", info.getText().raw());
426 else
427 RTPrintf("Error: failed to clone hard disk. No error message available!\n");
428 break;
429 }
430
431 CHECK_ERROR_BREAK(dstDisk, COMGETTER(Id)(uuid.asOutParam()));
432
433 RTPrintf("Clone hard disk created in format '%ls'. UUID: %s\n",
434 format.raw(), uuid.toString().raw());
435 }
436 while (0);
437
438 if (!remember && !dstDisk.isNull())
439 {
440 /* forget the created clone */
441 dstDisk->Close();
442 }
443
444 if (unknown)
445 {
446 /* close the unknown hard disk to forget it again */
447 srcDisk->Close();
448 }
449
450 return SUCCEEDED(rc) ? 0 : 1;
451}
452
453int handleConvertFromRaw(int argc, char *argv[])
454{
455 VDIMAGETYPE enmImgType = VD_IMAGE_TYPE_NORMAL;
456 bool fReadFromStdIn = false;
457 const char *format = "VDI";
458 const char *srcfilename = NULL;
459 const char *dstfilename = NULL;
460 const char *filesize = NULL;
461 unsigned uImageFlags = 0; /**< @todo allow creation of non-default image variants */
462 void *pvBuf = NULL;
463
464 for (int i = 0; i < argc; i++)
465 {
466 if (!strcmp(argv[i], "-static"))
467 {
468 enmImgType = VD_IMAGE_TYPE_FIXED;
469 }
470 else if (strcmp(argv[i], "-format") == 0)
471 {
472 if (argc <= i + 1)
473 {
474 return errorArgument("Missing argument to '%s'", argv[i]);
475 }
476 i++;
477 format = argv[i];
478 }
479 else
480 {
481 if (srcfilename)
482 {
483 if (dstfilename)
484 {
485 if (fReadFromStdIn && !filesize)
486 filesize = argv[i];
487 else
488 return errorSyntax(USAGE_CONVERTFROMRAW, "Incorrect number of parameters");
489 }
490 else
491 dstfilename = argv[i];
492 }
493 else
494 {
495 srcfilename = argv[i];
496#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
497 fReadFromStdIn = !strcmp(srcfilename, "stdin");
498#endif
499 }
500 }
501 }
502
503 if (!srcfilename || !dstfilename || (fReadFromStdIn && !filesize))
504 return errorSyntax(USAGE_CONVERTFROMRAW, "Incorrect number of parameters");
505 RTPrintf("Converting from raw image file=\"%s\" to file=\"%s\"...\n",
506 srcfilename, dstfilename);
507
508 int rc = VINF_SUCCESS;
509 PVBOXHDD pDisk = NULL;
510
511 PVDINTERFACE pVDIfs = NULL;
512 VDINTERFACE vdInterfaceError;
513 VDINTERFACEERROR vdInterfaceErrorCallbacks;
514 vdInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
515 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
516 vdInterfaceErrorCallbacks.pfnError = handleVDError;
517
518 rc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
519 &vdInterfaceErrorCallbacks, NULL, &pVDIfs);
520 AssertRC(rc);
521
522 /* open raw image file. */
523 RTFILE File;
524 if (fReadFromStdIn)
525 File = 0;
526 else
527 rc = RTFileOpen(&File, srcfilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
528 if (RT_FAILURE(rc))
529 {
530 RTPrintf("File=\"%s\" open error: %Rrf\n", srcfilename, rc);
531 goto out;
532 }
533
534 uint64_t cbFile;
535 /* get image size. */
536 if (fReadFromStdIn)
537 cbFile = RTStrToUInt64(filesize);
538 else
539 rc = RTFileGetSize(File, &cbFile);
540 if (RT_FAILURE(rc))
541 {
542 RTPrintf("Error getting image size for file \"%s\": %Rrc\n", srcfilename, rc);
543 goto out;
544 }
545
546 RTPrintf("Creating %s image with size %RU64 bytes (%RU64MB)...\n", (enmImgType == VD_IMAGE_TYPE_FIXED) ? "fixed" : "dynamic", cbFile, (cbFile + _1M - 1) / _1M);
547 char pszComment[256];
548 RTStrPrintf(pszComment, sizeof(pszComment), "Converted image from %s", srcfilename);
549 rc = VDCreate(pVDIfs, &pDisk);
550 if (RT_FAILURE(rc))
551 {
552 RTPrintf("Error while creating the virtual disk container: %Rrc\n", rc);
553 goto out;
554 }
555
556 Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) -
557 (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0);
558 PDMMEDIAGEOMETRY PCHS, LCHS;
559 PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383);
560 PCHS.cHeads = 16;
561 PCHS.cSectors = 63;
562 LCHS.cCylinders = 0;
563 LCHS.cHeads = 0;
564 LCHS.cSectors = 0;
565 rc = VDCreateBase(pDisk, format, dstfilename, enmImgType, cbFile,
566 uImageFlags, pszComment, &PCHS, &LCHS, NULL,
567 VD_OPEN_FLAGS_NORMAL, NULL, NULL);
568 if (RT_FAILURE(rc))
569 {
570 RTPrintf("Error while creating the disk image \"%s\": %Rrc\n", dstfilename, rc);
571 goto out;
572 }
573
574 size_t cbBuffer;
575 cbBuffer = _1M;
576 pvBuf = RTMemAlloc(cbBuffer);
577 if (!pvBuf)
578 {
579 rc = VERR_NO_MEMORY;
580 RTPrintf("Not enough memory allocating buffers for image \"%s\": %Rrc\n", dstfilename, rc);
581 goto out;
582 }
583
584 uint64_t offFile;
585 offFile = 0;
586 while (offFile < cbFile)
587 {
588 size_t cbRead;
589 size_t cbToRead;
590 cbRead = 0;
591 cbToRead = cbFile - offFile >= (uint64_t)cbBuffer ?
592 cbBuffer : (size_t) (cbFile - offFile);
593 rc = RTFileRead(File, pvBuf, cbToRead, &cbRead);
594 if (RT_FAILURE(rc) || !cbRead)
595 break;
596 rc = VDWrite(pDisk, offFile, pvBuf, cbRead);
597 if (RT_FAILURE(rc))
598 {
599 RTPrintf("Failed to write to disk image \"%s\": %Rrc\n", dstfilename, rc);
600 goto out;
601 }
602 offFile += cbRead;
603 }
604
605out:
606 if (pvBuf)
607 RTMemFree(pvBuf);
608 if (pDisk)
609 VDClose(pDisk, RT_FAILURE(rc));
610 if (File != NIL_RTFILE)
611 RTFileClose(File);
612
613 return RT_FAILURE(rc);
614}
615
616int handleAddiSCSIDisk(HandlerArg *a)
617{
618 HRESULT rc;
619 Bstr server;
620 Bstr target;
621 Bstr port;
622 Bstr lun;
623 Bstr username;
624 Bstr password;
625 Bstr comment;
626 bool fIntNet = false;
627
628 /* at least server and target */
629 if (a->argc < 4)
630 return errorSyntax(USAGE_ADDISCSIDISK, "Not enough parameters");
631
632 /* let's have a closer look at the arguments */
633 for (int i = 0; i < a->argc; i++)
634 {
635 if (strcmp(a->argv[i], "-server") == 0)
636 {
637 if (a->argc <= i + 1)
638 return errorArgument("Missing argument to '%s'", a->argv[i]);
639 i++;
640 server = a->argv[i];
641 }
642 else if (strcmp(a->argv[i], "-target") == 0)
643 {
644 if (a->argc <= i + 1)
645 return errorArgument("Missing argument to '%s'", a->argv[i]);
646 i++;
647 target = a->argv[i];
648 }
649 else if (strcmp(a->argv[i], "-port") == 0)
650 {
651 if (a->argc <= i + 1)
652 return errorArgument("Missing argument to '%s'", a->argv[i]);
653 i++;
654 port = a->argv[i];
655 }
656 else if (strcmp(a->argv[i], "-lun") == 0)
657 {
658 if (a->argc <= i + 1)
659 return errorArgument("Missing argument to '%s'", a->argv[i]);
660 i++;
661 lun = a->argv[i];
662 }
663 else if (strcmp(a->argv[i], "-encodedlun") == 0)
664 {
665 if (a->argc <= i + 1)
666 return errorArgument("Missing argument to '%s'", a->argv[i]);
667 i++;
668 lun = BstrFmt("enc%s", a->argv[i]);
669 }
670 else if (strcmp(a->argv[i], "-username") == 0)
671 {
672 if (a->argc <= i + 1)
673 return errorArgument("Missing argument to '%s'", a->argv[i]);
674 i++;
675 username = a->argv[i];
676 }
677 else if (strcmp(a->argv[i], "-password") == 0)
678 {
679 if (a->argc <= i + 1)
680 return errorArgument("Missing argument to '%s'", a->argv[i]);
681 i++;
682 password = a->argv[i];
683 }
684 else if (strcmp(a->argv[i], "-comment") == 0)
685 {
686 if (a->argc <= i + 1)
687 return errorArgument("Missing argument to '%s'", a->argv[i]);
688 i++;
689 comment = a->argv[i];
690 }
691 else if (strcmp(a->argv[i], "-intnet") == 0)
692 {
693 i++;
694 fIntNet = true;
695 }
696 else
697 return errorSyntax(USAGE_ADDISCSIDISK, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
698 }
699
700 /* check for required options */
701 if (!server || !target)
702 return errorSyntax(USAGE_ADDISCSIDISK, "Parameters -server and -target are required");
703
704 do
705 {
706 ComPtr<IHardDisk> hardDisk;
707 CHECK_ERROR_BREAK (a->virtualBox,
708 CreateHardDisk(Bstr ("iSCSI"),
709 BstrFmt ("%ls/%ls", server.raw(), target.raw()),
710 hardDisk.asOutParam()));
711 CheckComRCBreakRC (rc);
712
713 if (!comment.isNull())
714 CHECK_ERROR_BREAK(hardDisk, COMSETTER(Description)(comment));
715
716 if (!port.isNull())
717 server = BstrFmt ("%ls:%ls", server.raw(), port.raw());
718
719 com::SafeArray <BSTR> names;
720 com::SafeArray <BSTR> values;
721
722 Bstr ("TargetAddress").detachTo (names.appendedRaw());
723 server.detachTo (values.appendedRaw());
724 Bstr ("TargetName").detachTo (names.appendedRaw());
725 target.detachTo (values.appendedRaw());
726
727 if (!lun.isNull())
728 {
729 Bstr ("LUN").detachTo (names.appendedRaw());
730 lun.detachTo (values.appendedRaw());
731 }
732 if (!username.isNull())
733 {
734 Bstr ("InitiatorUsername").detachTo (names.appendedRaw());
735 username.detachTo (values.appendedRaw());
736 }
737 if (!password.isNull())
738 {
739 Bstr ("InitiatorSecret").detachTo (names.appendedRaw());
740 password.detachTo (values.appendedRaw());
741 }
742
743 /// @todo add -initiator option
744 Bstr ("InitiatorName").detachTo (names.appendedRaw());
745 Bstr ("iqn.2008-04.com.sun.virtualbox.initiator").detachTo (values.appendedRaw());
746
747 /// @todo add -targetName and -targetPassword options
748
749 if (fIntNet)
750 {
751 Bstr ("HostIPStack").detachTo (names.appendedRaw());
752 Bstr ("0").detachTo (values.appendedRaw());
753 }
754
755 CHECK_ERROR_BREAK (hardDisk,
756 SetProperties (ComSafeArrayAsInParam (names),
757 ComSafeArrayAsInParam (values)));
758
759 Guid guid;
760 CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));
761 RTPrintf("iSCSI disk created. UUID: %s\n", guid.toString().raw());
762 }
763 while (0);
764
765 return SUCCEEDED(rc) ? 0 : 1;
766}
767
768
769int handleShowHardDiskInfo(HandlerArg *a)
770{
771 HRESULT rc;
772
773 if (a->argc != 1)
774 return errorSyntax(USAGE_SHOWHDINFO, "Incorrect number of parameters");
775
776 ComPtr<IHardDisk> hardDisk;
777 Bstr filepath;
778
779 bool unknown = false;
780
781 /* first guess is that it's a UUID */
782 Guid uuid(a->argv[0]);
783 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
784 /* no? then it must be a filename */
785 if (FAILED (rc))
786 {
787 filepath = a->argv[0];
788 rc = a->virtualBox->FindHardDisk(filepath, hardDisk.asOutParam());
789 /* no? well, then it's an unkwnown image */
790 if (FAILED (rc))
791 {
792 CHECK_ERROR(a->virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
793 if (SUCCEEDED (rc))
794 {
795 unknown = true;
796 }
797 }
798 }
799 do
800 {
801 if (!SUCCEEDED(rc))
802 break;
803
804 hardDisk->COMGETTER(Id)(uuid.asOutParam());
805 RTPrintf("UUID: %s\n", uuid.toString().raw());
806
807 /* check for accessibility */
808 /// @todo NEWMEDIA check accessibility of all parents
809 /// @todo NEWMEDIA print the full state value
810 MediaState_T state;
811 CHECK_ERROR_BREAK (hardDisk, COMGETTER(State)(&state));
812 RTPrintf("Accessible: %s\n", state != MediaState_Inaccessible ? "yes" : "no");
813
814 if (state == MediaState_Inaccessible)
815 {
816 Bstr err;
817 CHECK_ERROR_BREAK (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()));
818 RTPrintf("Access Error: %lS\n", err.raw());
819 }
820
821 Bstr description;
822 hardDisk->COMGETTER(Description)(description.asOutParam());
823 if (description)
824 {
825 RTPrintf("Description: %lS\n", description.raw());
826 }
827
828 ULONG64 logicalSize;
829 hardDisk->COMGETTER(LogicalSize)(&logicalSize);
830 RTPrintf("Logical size: %llu MBytes\n", logicalSize);
831 ULONG64 actualSize;
832 hardDisk->COMGETTER(Size)(&actualSize);
833 RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
834
835 ComPtr <IHardDisk> parent;
836 hardDisk->COMGETTER(Parent) (parent.asOutParam());
837
838 HardDiskType_T type;
839 hardDisk->COMGETTER(Type)(&type);
840 const char *typeStr = "unknown";
841 switch (type)
842 {
843 case HardDiskType_Normal:
844 if (!parent.isNull())
845 typeStr = "normal (differencing)";
846 else
847 typeStr = "normal (base)";
848 break;
849 case HardDiskType_Immutable:
850 typeStr = "immutable";
851 break;
852 case HardDiskType_Writethrough:
853 typeStr = "writethrough";
854 break;
855 }
856 RTPrintf("Type: %s\n", typeStr);
857
858 Bstr format;
859 hardDisk->COMGETTER(Format)(format.asOutParam());
860 RTPrintf("Storage format: %lS\n", format.raw());
861
862 if (!unknown)
863 {
864 com::SafeGUIDArray machineIds;
865 hardDisk->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds));
866 for (size_t j = 0; j < machineIds.size(); ++ j)
867 {
868 ComPtr<IMachine> machine;
869 CHECK_ERROR(a->virtualBox, GetMachine(machineIds[j], machine.asOutParam()));
870 ASSERT(machine);
871 Bstr name;
872 machine->COMGETTER(Name)(name.asOutParam());
873 machine->COMGETTER(Id)(uuid.asOutParam());
874 RTPrintf("%s%lS (UUID: %RTuuid)\n",
875 j == 0 ? "In use by VMs: " : " ",
876 name.raw(), &machineIds[j]);
877 }
878 /// @todo NEWMEDIA check usage in snapshots too
879 /// @todo NEWMEDIA also list children
880 }
881
882 Bstr loc;
883 hardDisk->COMGETTER(Location)(loc.asOutParam());
884 RTPrintf("Location: %lS\n", loc.raw());
885
886 /* print out information specific for differencing hard disks */
887 if (!parent.isNull())
888 {
889 BOOL autoReset = FALSE;
890 hardDisk->COMGETTER(AutoReset)(&autoReset);
891 RTPrintf("Auto-Reset: %s\n", autoReset ? "on" : "off");
892 }
893 }
894 while (0);
895
896 if (unknown)
897 {
898 /* close the unknown hard disk to forget it again */
899 hardDisk->Close();
900 }
901
902 return SUCCEEDED(rc) ? 0 : 1;
903}
904
905int handleOpenMedium(HandlerArg *a)
906{
907 HRESULT rc;
908
909 if (a->argc < 2)
910 return errorSyntax(USAGE_REGISTERIMAGE, "Not enough parameters");
911
912 Bstr filepath(a->argv[1]);
913
914 if (strcmp(a->argv[0], "disk") == 0)
915 {
916 const char *type = NULL;
917 /* there can be a type parameter */
918 if ((a->argc > 2) && (a->argc != 4))
919 return errorSyntax(USAGE_REGISTERIMAGE, "Incorrect number of parameters");
920 if (a->argc == 4)
921 {
922 if (strcmp(a->argv[2], "-type") != 0)
923 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[2]).raw());
924 if ( (strcmp(a->argv[3], "normal") != 0)
925 && (strcmp(a->argv[3], "immutable") != 0)
926 && (strcmp(a->argv[3], "writethrough") != 0))
927 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(a->argv[3]).raw());
928 type = a->argv[3];
929 }
930
931 ComPtr<IHardDisk> hardDisk;
932 CHECK_ERROR(a->virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
933 if (SUCCEEDED(rc) && hardDisk)
934 {
935 /* change the type if requested */
936 if (type)
937 {
938 if (strcmp(type, "normal") == 0)
939 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));
940 else if (strcmp(type, "immutable") == 0)
941 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));
942 else if (strcmp(type, "writethrough") == 0)
943 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
944 }
945 }
946 }
947 else if (strcmp(a->argv[0], "dvd") == 0)
948 {
949 ComPtr<IDVDImage> dvdImage;
950 CHECK_ERROR(a->virtualBox, OpenDVDImage(filepath, Guid(), dvdImage.asOutParam()));
951 }
952 else if (strcmp(a->argv[0], "floppy") == 0)
953 {
954 ComPtr<IFloppyImage> floppyImage;
955 CHECK_ERROR(a->virtualBox, OpenFloppyImage(filepath, Guid(), floppyImage.asOutParam()));
956 }
957 else
958 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
959
960 return SUCCEEDED(rc) ? 0 : 1;
961}
962
963int handleCloseMedium(HandlerArg *a)
964{
965 HRESULT rc;
966
967 if (a->argc != 2)
968 return errorSyntax(USAGE_UNREGISTERIMAGE, "Incorrect number of parameters");
969
970 /* first guess is that it's a UUID */
971 Guid uuid(a->argv[1]);
972
973 if (strcmp(a->argv[0], "disk") == 0)
974 {
975 ComPtr<IHardDisk> hardDisk;
976 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
977 /* not a UUID or not registered? Then it must be a filename */
978 if (!hardDisk)
979 {
980 CHECK_ERROR(a->virtualBox, FindHardDisk(Bstr(a->argv[1]), hardDisk.asOutParam()));
981 }
982 if (SUCCEEDED(rc) && hardDisk)
983 {
984 CHECK_ERROR(hardDisk, Close());
985 }
986 }
987 else
988 if (strcmp(a->argv[0], "dvd") == 0)
989 {
990 ComPtr<IDVDImage> dvdImage;
991 rc = a->virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
992 /* not a UUID or not registered? Then it must be a filename */
993 if (!dvdImage)
994 {
995 CHECK_ERROR(a->virtualBox, FindDVDImage(Bstr(a->argv[1]), dvdImage.asOutParam()));
996 }
997 if (SUCCEEDED(rc) && dvdImage)
998 {
999 CHECK_ERROR(dvdImage, Close());
1000 }
1001 }
1002 else
1003 if (strcmp(a->argv[0], "floppy") == 0)
1004 {
1005 ComPtr<IFloppyImage> floppyImage;
1006 rc = a->virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
1007 /* not a UUID or not registered? Then it must be a filename */
1008 if (!floppyImage)
1009 {
1010 CHECK_ERROR(a->virtualBox, FindFloppyImage(Bstr(a->argv[1]), floppyImage.asOutParam()));
1011 }
1012 if (SUCCEEDED(rc) && floppyImage)
1013 {
1014 CHECK_ERROR(floppyImage, Close());
1015 }
1016 }
1017 else
1018 return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
1019
1020 return SUCCEEDED(rc) ? 0 : 1;
1021}
1022#endif /* !VBOX_ONLY_DOCS */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette