VirtualBox

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

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

API/HardDIsk: introduce parameter for specifying the image variant to be created.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.7 KB
Line 
1/* $Id: VBoxManageDisk.cpp 17825 2009-03-13 14:03:09Z 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, HardDiskVariant_Standard, progress.asOutParam()));
140 }
141 else
142 {
143 CHECK_ERROR(hardDisk, CreateDynamicStorage(sizeMB, HardDiskVariant_Standard, 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, HardDiskVariant_Standard, 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 /** @todo move the location stuff to Main, which can use pfnComposeName
708 * from the disk backends to construct the location properly. */
709 CHECK_ERROR_BREAK (a->virtualBox,
710 CreateHardDisk(Bstr ("iSCSI"),
711 BstrFmt ("%ls/%ls/%ls", server.raw(), target.raw(), lun.raw()),
712 hardDisk.asOutParam()));
713 CheckComRCBreakRC (rc);
714
715 if (!comment.isNull())
716 CHECK_ERROR_BREAK(hardDisk, COMSETTER(Description)(comment));
717
718 if (!port.isNull())
719 server = BstrFmt ("%ls:%ls", server.raw(), port.raw());
720
721 com::SafeArray <BSTR> names;
722 com::SafeArray <BSTR> values;
723
724 Bstr ("TargetAddress").detachTo (names.appendedRaw());
725 server.detachTo (values.appendedRaw());
726 Bstr ("TargetName").detachTo (names.appendedRaw());
727 target.detachTo (values.appendedRaw());
728
729 if (!lun.isNull())
730 {
731 Bstr ("LUN").detachTo (names.appendedRaw());
732 lun.detachTo (values.appendedRaw());
733 }
734 if (!username.isNull())
735 {
736 Bstr ("InitiatorUsername").detachTo (names.appendedRaw());
737 username.detachTo (values.appendedRaw());
738 }
739 if (!password.isNull())
740 {
741 Bstr ("InitiatorSecret").detachTo (names.appendedRaw());
742 password.detachTo (values.appendedRaw());
743 }
744
745 /// @todo add -initiator option
746 Bstr ("InitiatorName").detachTo (names.appendedRaw());
747 Bstr ("iqn.2008-04.com.sun.virtualbox.initiator").detachTo (values.appendedRaw());
748
749 /// @todo add -targetName and -targetPassword options
750
751 if (fIntNet)
752 {
753 Bstr ("HostIPStack").detachTo (names.appendedRaw());
754 Bstr ("0").detachTo (values.appendedRaw());
755 }
756
757 CHECK_ERROR_BREAK (hardDisk,
758 SetProperties (ComSafeArrayAsInParam (names),
759 ComSafeArrayAsInParam (values)));
760
761 Guid guid;
762 CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));
763 RTPrintf("iSCSI disk created. UUID: %s\n", guid.toString().raw());
764 }
765 while (0);
766
767 return SUCCEEDED(rc) ? 0 : 1;
768}
769
770
771int handleShowHardDiskInfo(HandlerArg *a)
772{
773 HRESULT rc;
774
775 if (a->argc != 1)
776 return errorSyntax(USAGE_SHOWHDINFO, "Incorrect number of parameters");
777
778 ComPtr<IHardDisk> hardDisk;
779 Bstr filepath;
780
781 bool unknown = false;
782
783 /* first guess is that it's a UUID */
784 Guid uuid(a->argv[0]);
785 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
786 /* no? then it must be a filename */
787 if (FAILED (rc))
788 {
789 filepath = a->argv[0];
790 rc = a->virtualBox->FindHardDisk(filepath, hardDisk.asOutParam());
791 /* no? well, then it's an unkwnown image */
792 if (FAILED (rc))
793 {
794 CHECK_ERROR(a->virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
795 if (SUCCEEDED (rc))
796 {
797 unknown = true;
798 }
799 }
800 }
801 do
802 {
803 if (!SUCCEEDED(rc))
804 break;
805
806 hardDisk->COMGETTER(Id)(uuid.asOutParam());
807 RTPrintf("UUID: %s\n", uuid.toString().raw());
808
809 /* check for accessibility */
810 /// @todo NEWMEDIA check accessibility of all parents
811 /// @todo NEWMEDIA print the full state value
812 MediaState_T state;
813 CHECK_ERROR_BREAK (hardDisk, COMGETTER(State)(&state));
814 RTPrintf("Accessible: %s\n", state != MediaState_Inaccessible ? "yes" : "no");
815
816 if (state == MediaState_Inaccessible)
817 {
818 Bstr err;
819 CHECK_ERROR_BREAK (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()));
820 RTPrintf("Access Error: %lS\n", err.raw());
821 }
822
823 Bstr description;
824 hardDisk->COMGETTER(Description)(description.asOutParam());
825 if (description)
826 {
827 RTPrintf("Description: %lS\n", description.raw());
828 }
829
830 ULONG64 logicalSize;
831 hardDisk->COMGETTER(LogicalSize)(&logicalSize);
832 RTPrintf("Logical size: %llu MBytes\n", logicalSize);
833 ULONG64 actualSize;
834 hardDisk->COMGETTER(Size)(&actualSize);
835 RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
836
837 ComPtr <IHardDisk> parent;
838 hardDisk->COMGETTER(Parent) (parent.asOutParam());
839
840 HardDiskType_T type;
841 hardDisk->COMGETTER(Type)(&type);
842 const char *typeStr = "unknown";
843 switch (type)
844 {
845 case HardDiskType_Normal:
846 if (!parent.isNull())
847 typeStr = "normal (differencing)";
848 else
849 typeStr = "normal (base)";
850 break;
851 case HardDiskType_Immutable:
852 typeStr = "immutable";
853 break;
854 case HardDiskType_Writethrough:
855 typeStr = "writethrough";
856 break;
857 }
858 RTPrintf("Type: %s\n", typeStr);
859
860 Bstr format;
861 hardDisk->COMGETTER(Format)(format.asOutParam());
862 RTPrintf("Storage format: %lS\n", format.raw());
863
864 if (!unknown)
865 {
866 com::SafeGUIDArray machineIds;
867 hardDisk->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds));
868 for (size_t j = 0; j < machineIds.size(); ++ j)
869 {
870 ComPtr<IMachine> machine;
871 CHECK_ERROR(a->virtualBox, GetMachine(machineIds[j], machine.asOutParam()));
872 ASSERT(machine);
873 Bstr name;
874 machine->COMGETTER(Name)(name.asOutParam());
875 machine->COMGETTER(Id)(uuid.asOutParam());
876 RTPrintf("%s%lS (UUID: %RTuuid)\n",
877 j == 0 ? "In use by VMs: " : " ",
878 name.raw(), &machineIds[j]);
879 }
880 /// @todo NEWMEDIA check usage in snapshots too
881 /// @todo NEWMEDIA also list children
882 }
883
884 Bstr loc;
885 hardDisk->COMGETTER(Location)(loc.asOutParam());
886 RTPrintf("Location: %lS\n", loc.raw());
887
888 /* print out information specific for differencing hard disks */
889 if (!parent.isNull())
890 {
891 BOOL autoReset = FALSE;
892 hardDisk->COMGETTER(AutoReset)(&autoReset);
893 RTPrintf("Auto-Reset: %s\n", autoReset ? "on" : "off");
894 }
895 }
896 while (0);
897
898 if (unknown)
899 {
900 /* close the unknown hard disk to forget it again */
901 hardDisk->Close();
902 }
903
904 return SUCCEEDED(rc) ? 0 : 1;
905}
906
907int handleOpenMedium(HandlerArg *a)
908{
909 HRESULT rc;
910
911 if (a->argc < 2)
912 return errorSyntax(USAGE_REGISTERIMAGE, "Not enough parameters");
913
914 Bstr filepath(a->argv[1]);
915
916 if (strcmp(a->argv[0], "disk") == 0)
917 {
918 const char *type = NULL;
919 /* there can be a type parameter */
920 if ((a->argc > 2) && (a->argc != 4))
921 return errorSyntax(USAGE_REGISTERIMAGE, "Incorrect number of parameters");
922 if (a->argc == 4)
923 {
924 if (strcmp(a->argv[2], "-type") != 0)
925 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[2]).raw());
926 if ( (strcmp(a->argv[3], "normal") != 0)
927 && (strcmp(a->argv[3], "immutable") != 0)
928 && (strcmp(a->argv[3], "writethrough") != 0))
929 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(a->argv[3]).raw());
930 type = a->argv[3];
931 }
932
933 ComPtr<IHardDisk> hardDisk;
934 CHECK_ERROR(a->virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
935 if (SUCCEEDED(rc) && hardDisk)
936 {
937 /* change the type if requested */
938 if (type)
939 {
940 if (strcmp(type, "normal") == 0)
941 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));
942 else if (strcmp(type, "immutable") == 0)
943 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));
944 else if (strcmp(type, "writethrough") == 0)
945 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
946 }
947 }
948 }
949 else if (strcmp(a->argv[0], "dvd") == 0)
950 {
951 ComPtr<IDVDImage> dvdImage;
952 CHECK_ERROR(a->virtualBox, OpenDVDImage(filepath, Guid(), dvdImage.asOutParam()));
953 }
954 else if (strcmp(a->argv[0], "floppy") == 0)
955 {
956 ComPtr<IFloppyImage> floppyImage;
957 CHECK_ERROR(a->virtualBox, OpenFloppyImage(filepath, Guid(), floppyImage.asOutParam()));
958 }
959 else
960 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
961
962 return SUCCEEDED(rc) ? 0 : 1;
963}
964
965int handleCloseMedium(HandlerArg *a)
966{
967 HRESULT rc;
968
969 if (a->argc != 2)
970 return errorSyntax(USAGE_UNREGISTERIMAGE, "Incorrect number of parameters");
971
972 /* first guess is that it's a UUID */
973 Guid uuid(a->argv[1]);
974
975 if (strcmp(a->argv[0], "disk") == 0)
976 {
977 ComPtr<IHardDisk> hardDisk;
978 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
979 /* not a UUID or not registered? Then it must be a filename */
980 if (!hardDisk)
981 {
982 CHECK_ERROR(a->virtualBox, FindHardDisk(Bstr(a->argv[1]), hardDisk.asOutParam()));
983 }
984 if (SUCCEEDED(rc) && hardDisk)
985 {
986 CHECK_ERROR(hardDisk, Close());
987 }
988 }
989 else
990 if (strcmp(a->argv[0], "dvd") == 0)
991 {
992 ComPtr<IDVDImage> dvdImage;
993 rc = a->virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
994 /* not a UUID or not registered? Then it must be a filename */
995 if (!dvdImage)
996 {
997 CHECK_ERROR(a->virtualBox, FindDVDImage(Bstr(a->argv[1]), dvdImage.asOutParam()));
998 }
999 if (SUCCEEDED(rc) && dvdImage)
1000 {
1001 CHECK_ERROR(dvdImage, Close());
1002 }
1003 }
1004 else
1005 if (strcmp(a->argv[0], "floppy") == 0)
1006 {
1007 ComPtr<IFloppyImage> floppyImage;
1008 rc = a->virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
1009 /* not a UUID or not registered? Then it must be a filename */
1010 if (!floppyImage)
1011 {
1012 CHECK_ERROR(a->virtualBox, FindFloppyImage(Bstr(a->argv[1]), floppyImage.asOutParam()));
1013 }
1014 if (SUCCEEDED(rc) && floppyImage)
1015 {
1016 CHECK_ERROR(floppyImage, Close());
1017 }
1018 }
1019 else
1020 return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
1021
1022 return SUCCEEDED(rc) ? 0 : 1;
1023}
1024#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